I use an XOR based implementation in the GetHashCode implementation of most of my equatable types.
I've read several posts explaining why it is not the best solution so I decided to implement GetHashCode as suggested by Jon Skeet:
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 23 + field1.GetHashCode();
hash = hash * 23 + field2.GetHashCode();
hash = hash * 23 + field3.GetHashCode();
return hash;
}
Since the code is likely to be similar in most implementations, I tried to build a helper class to calculate hash codes for all my classes. It should be an easy thing to do but one of the main constraints with GetHashCode is it has to be fast. Therefore any implementation involving allocation is probably a no go (for instance, the use of a non static class).
Ideally a call to such a method would look like:
public override GetHashCode() => HashCodeCalculator.Calculate(X, Y, Z);
And have all the logic (unchecked + primes + null check...). But the use of a params parameter implicitly creates an array.
Is it best to duplicate the hashing algorithm in each class instead? Or is a class like the following as efficient?
public static class HashCalculator
{
private const int _seed = 5923;
private const int _multiplier = 7481;
public static int Add(object value) => Add(_seed, value);
public static int Add(int current, object value)
{
int valueHashCode = (value != null) ? value.GetHashCode() : 0;
unchecked
{
return (current * _multiplier) + valueHashCode;
}
}
}
which can then be used like this:
public override int GetHashCode()
{
int result = HashCalculator.Add(Prop1);
result = HashCalculator.Add(result, Prop2);
return result;
}
You can create overloads for various small fixed numbers of parameters (2, 3, 4, etc. until you decide to stop), in order to avoid the array allocation, and then have a params overload that only ever needs to be used when there is a particularly large number of operands, at which point the overhead of the array allocation is less likely to be a problem (as it'll be a smaller percentage of the work done).
I can see why it is so tempting to have some kind of helper tool to calc hashes, but in this case efficiency is in great contradiction to convenience. You are trying to have a cookie and eat it and the answer depends on how much cookie you are willing to left over :)
One additional method call? Then it should have signature simmilar to
int HashCode(params int subhashcodes)
but invoking it will be ugly because you need to provide hashcodes of fields as parameters.
One method call and boxing? Then you can change int to object in previous signature to call fields hashcodes inside your method (I'm not fully sure that there will be no boxing in first case - feel free to correct me)
Personally I will stick to writing it by hand (or by Resharper).
After benchmarking it appears that using a struct like the following is almost as efficient as XORing and nicely encapsulates hash codes calculation.
/// <summary>
/// Calculates a hash code based on multiple hash codes.
/// </summary>
public struct HashCode
{
private const int _seed = 5923;
private const int _multiplier = 7481;
/// <summary>
/// Builds a new hash code.
/// </summary>
/// <returns>The built hash code.</returns>
public static HashCode Build() => new HashCode(_seed);
/// <summary>
/// Constructor from a hash value.
/// </summary>
/// <param name="value">Hash value.</param>
private HashCode(int value)
{
_value = value;
}
/// <summary>
/// Builds a new hash code and initializes it from a hash code source.
/// </summary>
/// <param name="hashCodeSource">Item from which a hash code can be extracted (using GetHashCode).</param>
public HashCode(object hashCodeSource)
{
int sourceHashCode = GetHashCode(hashCodeSource);
_value = AddValue(_seed, sourceHashCode);
}
private readonly int _value;
/// <summary>
/// Returns the hash code for a given hash code source (0 if the source is null).
/// </summary>
/// <param name="hashCodeSource">Item from which a hash code can be extracted (using GetHashCode).</param>
/// <returns>The hash code.</returns>
private static int GetHashCode(object hashCodeSource) => (hashCodeSource != null) ? hashCodeSource.GetHashCode() : 0;
/// <summary>
/// Adds a new hash value to a hash code.
/// </summary>
/// <param name="currentValue">Current hash value.</param>
/// <param name="valueToAdd">Value to add.</param>
/// <returns>The new hash value.</returns>
private static int AddValue(int currentValue, int valueToAdd)
{
unchecked
{
return (currentValue * _multiplier) + valueToAdd;
}
}
/// <summary>
/// Adds an object's hash code.
/// </summary>
/// <param name="hashCode">Hash code to which the object's hash code has to be added.</param>
/// <param name="hashCodeSource">Item from which a hash code can be extracted (using GetHashCode).</param>
/// <returns>The updated hash instance.</returns>
public static HashCode operator +(HashCode hashCode, object hashCodeSource)
{
int sourceHashCode = GetHashCode(hashCodeSource);
int newHashValue = AddValue(hashCode._value, sourceHashCode);
return new HashCode(newHashValue);
}
/// <summary>
/// Implicit cast operator to int.
/// </summary>
/// <param name="hashCode">Hash code to convert.</param>
public static implicit operator int(HashCode hashCode) => hashCode._value;
}
which can be used like this:
public override int GetHashCode() => new HashCode(Prop1) + Prop2;
EDIT:
.net core now has such a HashCode struct.
Related
I have implemented some sort of LINQ Range operator and do want to have a test which will verify that the Range operator is actually deferred.
My Range operator methods:
/// <summary>
/// The Range static method, validation part.
/// </summary>
/// <param name="start">The start.</param>
/// <param name="count">The count.</param>
/// <returns></returns>
public static IEnumerable<int> Range(int start, int count)
{
long max = ((long) start) + count - 1;
if (count < 0 || max > Int32.MaxValue) throw new ArgumentOutOfRangeException(nameof(count));
return RangeIterator(start, count);
}
/// <summary>
/// The Range operator iterator.
/// </summary>
/// <param name="start">The start.</param>
/// <param name="count">The count.</param>
/// <returns></returns>
static IEnumerable<int> RangeIterator(int start, int count)
{
for (int i = 0; i < count; ++i)
{
yield return start + i;
}
}
For the other deferred operators I have created ThrowingExceptionEnumerable utility class, which helps with testing:
/// <summary>
/// The class responsible for verifying that linq operator is deferred.
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class ThrowingExceptionEnumerable<T> : IEnumerable<T>
{
/// <summary>
/// The methods throws <see cref="InvalidOperationException"/>.
/// </summary>
/// <returns></returns>
public IEnumerator<T> GetEnumerator()
{
throw new InvalidOperationException();
}
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// The method which checks that the given <see cref="deferredFunction"/> actually uses deferred execution.
/// When the function just call itself it should not throw an exception. But, when using the result
/// by calling <see cref="GetEnumerator"/> and than GetNext() methods should throws the <see cref="InvalidOperationException"/>.
/// </summary>
/// <typeparam name="TSource">The deferred function source type.</typeparam>
/// <typeparam name="TResult">The deferred function result type.</typeparam>
/// <param name="deferredFunction">The deferred function (unit of work under the test).</param>
public static void AssertDeferred<TSource,TResult>(
Func<IEnumerable<TSource>, IEnumerable<TResult>> deferredFunction)
{
var source = new ThrowingExceptionEnumerable<TSource>();
// Does not throw any exception here, because GetEnumerator() method is not yet used.
var result = deferredFunction(source);
// Does not throw InvalidOperationException even here, despite the fact that we retrieve the enumerator.
using var iterator = result.GetEnumerator();
Assert.Throws<InvalidOperationException>(() => iterator.MoveNext());
}
And for instance deferred Select operator has the following test:
/// <summary>
/// Should check that Select operator is deferred.
/// </summary>
[Fact]
public void VerifySelectExecutionIsDeferred()
{
ThrowingExceptionEnumerable<int>.AssertDeferred<int, int>(source => source.Select(x => x));
}
The first problem I have faced during writing such unit test for the Range operator is that Range is actually a static method and not an extension method. Also the thing is, that Range signature does not have a source parameter, so the same approach can not be used.
Do you have some clever ideas, how it can be tested?
External code isn't going to be able to do anything to verify that the values are generated on the fly. The only actual difference between a method like this and one that materializes a collection and returns it is the memory footprint at scale, which is quite difficult to reliably test in a unit test.
You can clearly tell that it doesn't do that my looking at the code, but you'd need to alter the implementation in some pretty significant way to end up with something that would allow you to verify that in a unit test (such as writing a more generalized "Generate" method that used a delegate to generate the next value).
If you had some sort of hard requirement that your implementation has unit tests to verify such things, I'd write such a Generate method, implement your Range method by calling Generate, write a unit test to verify that Generate doesn't call the delegate until generating the next value in the sequence, and then assert that the Range method defers execution because it uses Generate to produce its sequence. I wouldn't want to do this in production code though, this would really be just a way of meeting the requirement and making some sacrifices in readability and (mild) performance for the sake of it.
I'm using the fluent pattern for helping with unit testing, and result object building. The biggest pain point of the fluent builder pattern is having to define all these With____ methods for each and every property that I might want to set.
When it comes to an object with maybe 30 fields that I might want to set, I don't exactly want to write out 30 methods that all pretty much do the same thing. I'd rather just write out something dynamic that can handle all the similar logic for me.
For example (psuedo code)
for each property in this.properties
define method( property.name with
return type: this.class,
parameter types: [property.type]){
set property property.name, parameters[0]
return this
}
Here is what I have so far in c#
var properties = typeof(EngineModelBuilder).GetProperties();
foreach (var property in properties){
// how do I create a method here with the property?
// a property has .PropertyType and a .Name
// and the return type is always going to be 'this'
}
For reference, here is how a normal fluent builder method looks:
public EngineModelBuilder WithDescription(string description)
{
_description = description;
return this;
}
This is the class I came up with. It utilizes C#'s dynamic object to use the "method_missing" approach of run-time functionality.
Note that method_missing is from Ruby, and is commonly used for this kind of dynamic behavior.
DynamicBuilder.cs:
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace PGenCore
{
/// <summary>
/// TODO: test different field retreival techniques (using fields from T, and managing in a Dictionary)
/// - how would we define defaults?
///
///
/// Usage:
/// dynamic objectBuilder = new ObjectBuilder();
/// var object = objectBuilder
/// .WithObjectFieldName(appropriateValue)
/// .WithObjectField(appropriateValue2)
/// .Build();
///
/// </summary>
/// <typeparam name="T">Type to Build</typeparam>
public class DynamicBuilder<T> : DynamicObject
{
#region List of FieldInformation
protected FieldInfo[] FieldInfos;
public FieldInfo[] FieldInformation
{
get
{
// don't GetFields all the time
if (FieldInfos != null) return FieldInfos;
FieldInfos = this.GetType().GetFields(
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance);
return FieldInfos;
}
}
#endregion
#region Utility
/// <summary>
/// converts FieldName to _fieldName
/// </summary>
/// <param name="publicName"></param>
/// <returns></returns>
public static string PublicNameToPrivate(string publicName)
{
var propertyLowerFirstLetterName = char.ToLower(
publicName[0]) + publicName.Substring(1);
var privateName = "_" + propertyLowerFirstLetterName;
return privateName;
}
#endregion
#region Method is Missing? Check for With{FieldName} Pattern
/// <summary>
/// Inherited form DynamicObject.
/// Ran before each method call.
///
///
/// Note: Currently only works for setting one value
/// at a time.
/// e.g.: instance.Object = value
/// </summary>
/// <param name="binder"></param>
/// <param name="args"></param>
/// <param name="result"></param>
/// <returns></returns>
public override bool TryInvokeMember(
InvokeMemberBinder binder,
object[] args,
out object result)
{
var firstArgument = args[0];
var methodName = binder.Name;
var propertyRootName = methodName;
// following the builder pattern,
// methods that participate in building T,
// return this so we can chain building methods.
result = this;
// for booleans, since the field / property should be named as
// a question, using "With" doesn't make sense.
// so, this logic is only needed when we are not setting a
// boolean field.
if (!(firstArgument is bool))
{
// if we are not setting a bool, and we aren't starting
// with "With", this method is not part of the
// fluent builder pattern.
if (!methodName.Contains("With")) return false;
propertyRootName = methodName.Replace("With", "");
}
// convert to _privateFieldName
// TODO: think about dynamicly having fields in a Dictionary,
// rather than having to specify them
var builderFieldName = PublicNameToPrivate(propertyRootName);
// find matching field name, given the method name
var fieldInfo = FieldInformation
.FirstOrDefault(
field => field.Name == builderFieldName
);
// if the field was not found, abort
if (fieldInfo == null) return false;
// set the field to the value in args
fieldInfo.SetValue(this, firstArgument);
return true;
}
#endregion
/// <summary>
/// Returns the built object
/// </summary>
/// <returns></returns>
public virtual T Build()
{
throw new NotImplementedException();
}
/// <summary>
/// for any complex associations
/// - building lists of items
/// - building anything else that isn't just an easy vavlue.
/// </summary>
public virtual void SetRelationshipDefaults()
{
throw new NotImplementedException();
}
}
}
Tests of usage can be seen here: https://github.com/NullVoxPopuli/Procedural-Builder/blob/master/ProceduralBuilder.Test/DynamicBuilderTest.cs
I have an external library that takes an IntPtr. Is there any safe way to do this...
int BytesWritten = 0;
Output.WriteBytes(buffer, new IntPtr(&BytesWritten));
...without having to use 'unsafe' code? I'm not that familiar with IntPtrs, but I'd like to do something like this:
fixed int BytesWritten = 0;
Output.WriteBytes(buffer, IntPtr.GetSafeIntPtr(ref BytesWritten));
...in such a way that I don't need to compile with /unsafe.
I can't change the WriteBytes function, it's an external function.
It seems like there should be some sort of cast between 'ref int' and IntPtr, but I have not had luck finding it.
I assume that Output.WriteBytes is a [DllImport] method. Can you post the declaration?
You should be able to avoid the pointer by declaring the last parameter as out int instead of IntPtr -- let the P/Invoke marshaller do the rest.
Yes, there is. You can use P/Invoke for your code. It will create the pointer for you automagically. Something like this:
[DllImport("yourlib", SetLastError=true)]
static extern bool WriteBytes(
[MarshalAs(UnmanagedType.LPArray)]
byte [] buffer,
ref int BytesWritten);
(I added the array as a bonus). More info on P/Invoke can be found, with gazillion examples, at pinvoke.net.
Each parameter above can take out, in and ref. Out and ref parameters are translated as pointers, where an ref-parameter is two-way.
Here is a class that will provide you with a safe IntPtr implementation. It derives from the SafeHandleZeroOrMinusOneIsInvalid class, provided by the .NET framework.
/// <summary>
/// IntPtr wrapper which can be used as result of
/// Marshal.AllocHGlobal operation.
/// Call Marshal.FreeHGlobal when disposed or finalized.
/// </summary>
class HGlobalSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
{
/// <summary>
/// Creates new instance with given IntPtr value
/// </summary>
public HGlobalSafeHandle(IntPtr ptr) : base(ptr, true)
{
}
/// <summary>
/// Creates new instance with zero IntPtr
/// </summary>
public HGlobalSafeHandle() : base(IntPtr.Zero, true)
{
}
/// <summary>
/// Creates new instance which allocates unmanaged memory of given size
/// Can throw OutOfMemoryException
/// </summary>
public HGlobalSafeHandle(int size) :
base(Marshal.AllocHGlobal(size), true)
{
}
/// <summary>
/// Allows to assign IntPtr to HGlobalSafeHandle
/// </summary>
public static implicit operator HGlobalSafeHandle(IntPtr ptr)
{
return new HGlobalSafeHandle(ptr);
}
/// <summary>
/// Allows to use HGlobalSafeHandle as IntPtr
/// </summary>
public static implicit operator IntPtr(HGlobalSafeHandle h)
{
return h.handle;
}
/// <summary>
/// Called when object is disposed or finalized.
/// </summary>
override protected bool ReleaseHandle()
{
Marshal.FreeHGlobal(handle);
return true;
}
/// <summary>
/// Defines invalid (null) handle value.
/// </summary>
public override bool IsInvalid
{
get
{
return (handle == IntPtr.Zero);
}
}
}
Why isn't there a bit structure in C#?
For what's worth, here is a full-fledged bit structure, complete with int and bool casting and arithmetic operations. Probably not perfect, but works fine for me. Enjoy!
/// <summary>
/// Represents a single bit that can be implicitly cast to/from and compared
/// with booleans and integers.
/// </summary>
/// <remarks>
/// <para>
/// An instance with a value of one is equal to any non-zero integer and is true,
/// an instance with a value of zero is equal to the integer zero and is false.
/// </para>
/// <para>
/// Arithmetic and logical AND, OR and NOT, as well as arithmetic XOR, are supported.
/// </para>
/// </remarks>
public struct Bit
{
/// <summary>
/// Creates a new instance with the specified value.
/// </summary>
/// <param name="value"></param>
public Bit(int value) : this()
{
Value = value == 0 ? 0 : 1;
}
/// <summary>
/// Gets the value of the bit, 0 or 1.
/// </summary>
public int Value { get; private set; }
#region Implicit conversions
public static implicit operator Bit(int value)
{
return new Bit(value);
}
public static implicit operator int(Bit value)
{
return value.Value;
}
public static implicit operator bool(Bit value)
{
return value.Value == 1;
}
public static implicit operator Bit(bool value)
{
return new Bit(value ? 1 : 0);
}
#endregion
#region Arithmetic operators
public static Bit operator |(Bit value1, Bit value2)
{
return value1.Value | value2.Value;
}
public static Bit operator &(Bit value1, Bit value2)
{
return value1.Value & value2.Value;
}
public static Bit operator ^(Bit value1, Bit value2)
{
return value1.Value ^ value2.Value;
}
public static Bit operator ~(Bit value)
{
return new Bit(value.Value ^ 1);
}
public static Bit operator !(Bit value)
{
return ~value;
}
#endregion
#region The true and false operators
public static bool operator true(Bit value)
{
return value.Value == 1;
}
public static bool operator false(Bit value)
{
return value.Value == 0;
}
#endregion
#region Comparison operators
public static bool operator ==(Bit bitValue, int intValue)
{
return
(bitValue.Value == 0 && intValue == 0) ||
(bitValue.Value == 1 && intValue != 0);
}
public static bool operator !=(Bit bitValue, int intValue)
{
return !(bitValue == intValue);
}
public override bool Equals(object obj)
{
if(obj is int)
return this == (int)obj;
else
return base.Equals(obj);
}
#endregion
}
It is called a boolean. At least, it would serve the basic function, right? You don't twiddle bits that often in C# (at least, I don't), and if you need to you can use the built in operations.
There is a BitArray class..
What would you want to do with it? Bear in mind that the CLR isn't going to try to pack multiple variables into a byte, so having one on its own would be no more useful than boolean. If you wanted to have a collection of them - well, that's what BitArray is for, as David pointed out.
If we did have a Bit structure, I suspect people would expect multiple Bit variables to be packed efficiently in memory - by not having the type in the first place, we avoid that expectation and lead people towards other solutions such as BitArray.
If you have a collection of bit flags, then using enums (with falgs attribute) and integers work a long way.
Though maybe there are rare exceptions, computers are not designed or intended to manipulate or allocate individual bits. Even at the lowest levels (assembly or pure machine language), you will not be able to allocate or access an individual bit. You have the same tools available in this regard as you have from any programming level: bytes and bitwise operations.
Along with the BitArray class already mentioned there is a also the more efficient BitVector32 Structure.
BitVector32 is more efficient than BitArray for Boolean values and
small integers that are used internally. A BitArray can grow
indefinitely as needed, but it has the memory and performance overhead
that a class instance requires. In contrast, a BitVector32 uses only
32 bits.
Keep in mind you are limited to 32 values.
Examples of BitVector32 usage at Dotnetpearls.com
You can do this now in C# 7.0!
public const int One = 0b0001;
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#numeric-literal-syntax-improvements
What is SafeHandle? how does it differ from IntPtr? When should I use one? What are its advantages?
You should use a derivative of SafeHandle whenever possible where managed code is receiving an IntPtr from unmanaged code. While the name, general use, and even documentation of the SafeHandle class implies that it is only supposed to be used to contain Windows operating system handles, a few internal .NET framework classes such as Microsoft.Win32.SafeHandles.SafeLocalAllocHandle and those that derive from the publicly available abstract class System.Runtime.InteropServices.SafeBuffer also use it to guarantee that other unmanaged resources such as dynamically allocated structs and arrays are freed. In general, I believe that it is good practice to create a derivative of this class whenever an IntPtr is returned to managed code from unmanaged code even if it doesn't require cleanup.
The established purpose of a SafeHandle is to guarantee that even if the world is ending (e.g. an AppDomain is being unloaded or a StackOverflowException occurs) the .NET framework should make absolutely sure that the finalizer for the SafeHandle is called to close or deallocate the unmanaged entity being referred to by the wrapped IntPtr. The SafeHandle class achieves this by inheriting from the CriticalFinalizerObject class. Inheriting from this class does, however, place upon the inheritor the obligation of not totally screwing up the state of the process when the finalizer is called, which is likely why it is not often used for entities other than Windows operating system handles. The .NET framework also provides some weak finalization ordering so that it is safe to interact with a SafeHandle object in the finalizer of any class that does not inherit from CriticalFinalizerObject, but circumstances in which that is necessary should be few and far between.
Ideally, a SafeHandle-derived class should also be used to more safely interact with an unmanaged entity reference by encapsulating expected functionality within the derived class. A well-written class that inherits from SafeHandle should have a specific purpose in mind and should provide methods that are sufficient to prevent any developer using it for that purpose from ever needing to interact directly with the IntPtr it contains. Adding such methods also provides other developers with a clear idea of what the result of an unmanaged method call is to be used for in a managed context. A class that inherits from SafeHandle can be used for this even if no cleanup is required on the pointer that the unmanaged method returns by calling base(false) in the constructor for the class.
Two examples that use classes which derive from SafeHandle to safely clean up a reference to an unmanaged entity and encapsulate functionality related to the unmanaged entity are below. The first example is a more traditional scenario in which a user token returned by LogonUser is wrapped by an instance of the SafeTokenHandle class. This class will call CloseHandle on the token when the object is disposed or finalized. It also includes a method called GetWindowsIdentity that returns a WindowsIdentity object for the user represented by the user token. The second example uses Windows built-in function CommandLineToArgvW to parse a command line. This function returns a pointer to an array contained a contiguous block of memory that can be freed by a single call to LocalFree. The SafeLocalAllocWStrArray class (which inherits from class SafeLocalAllocArray which is also defined in this example) will call LocalFree on the array when object is disposed or finalized. It also includes a function that will copy the contents of the unmanaged array to a managed array.
static class Examples
{
static void Example1_SafeUserToken()
{
const string user = "SomeLocalUser";
const string domain = null;
const string password = "ExamplePassword";
NativeMethods.SafeTokenHandle userToken;
WindowsIdentity identity;
NativeMethods.LogonUser(user, domain, password, NativeMethods.LogonType.LOGON32_LOGON_INTERACTIVE, NativeMethods.LogonProvider.LOGON32_PROVIDER_DEFAULT, out userToken);
using (userToken)
{
// get a WindowsIdentity object for the user
// WindowsIdentity will duplicate the token, so it is safe to free the original token after this is called
identity = userToken.GetWindowsIdentity();
}
// impersonate the user
using (identity)
using (WindowsImpersonationContext impersonationContext = identity.Impersonate())
{
Console.WriteLine("I'm running as {0}!", Thread.CurrentPrincipal.Identity.Name);
}
}
static void Example2_SafeLocalAllocWStrArray()
{
const string commandLine = "/example /command";
int argc;
string[] args;
using (NativeMethods.SafeLocalAllocWStrArray argv = NativeMethods.CommandLineToArgvW(commandLine, out argc))
{
// CommandLineToArgvW returns NULL on failure; since SafeLocalAllocWStrArray inherits from
// SafeHandleZeroOrMinusOneIsInvalid, it will see this value as invalid
// if that happens, throw an exception containing the last Win32 error that occurred
if (argv.IsInvalid)
{
int lastError = Marshal.GetHRForLastWin32Error();
throw new Win32Exception(lastError, "An error occurred when calling CommandLineToArgvW.");
}
// the one unsafe aspect of this is that the developer calling this function must be trusted to
// pass in an array of length argc or specify the length of the copy as the value of argc
// if the developer does not do this, the array may end up containing some garbage or an
// AccessViolationException could be thrown
args = new string[argc];
argv.CopyTo(args);
}
for (int i = 0; i < args.Length; ++i)
{
Console.WriteLine("Argument {0}: {1}", i, args[i]);
}
}
}
/// <summary>
/// P/Invoke methods and helper classes used by this example.
/// </summary>
internal static class NativeMethods
{
// documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378184(v=vs.85).aspx
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, LogonType dwLogonType, LogonProvider dwLogonProvider, out SafeTokenHandle phToken);
// documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr handle);
// documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx
[DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern SafeLocalAllocWStrArray CommandLineToArgvW(string lpCmdLine, out int pNumArgs);
// documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366730(v=vs.85).aspx
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LocalFree(IntPtr hLocal);
/// <summary>
/// Wraps a handle to a user token.
/// </summary>
public class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
/// <summary>
/// Creates a new SafeTokenHandle. This constructor should only be called by P/Invoke.
/// </summary>
private SafeTokenHandle()
: base(true)
{
}
/// <summary>
/// Creates a new SafeTokenHandle to wrap the specified user token.
/// </summary>
/// <param name="arrayPointer">The user token to wrap.</param>
/// <param name="ownHandle"><c>true</c> to close the token when this object is disposed or finalized,
/// <c>false</c> otherwise.</param>
public SafeTokenHandle(IntPtr handle, bool ownHandle)
: base(ownHandle)
{
this.SetHandle(handle);
}
/// <summary>
/// Provides a <see cref="WindowsIdentity" /> object created from this user token. Depending
/// on the type of token, this can be used to impersonate the user. The WindowsIdentity
/// class will duplicate the token, so it is safe to use the WindowsIdentity object created by
/// this method after disposing this object.
/// </summary>
/// <returns>a <see cref="WindowsIdentity" /> for the user that this token represents.</returns>
/// <exception cref="InvalidOperationException">This object does not contain a valid handle.</exception>
/// <exception cref="ObjectDisposedException">This object has been disposed and its token has
/// been released.</exception>
public WindowsIdentity GetWindowsIdentity()
{
if (this.IsClosed)
{
throw new ObjectDisposedException("The user token has been released.");
}
if (this.IsInvalid)
{
throw new InvalidOperationException("The user token is invalid.");
}
return new WindowsIdentity(this.handle);
}
/// <summary>
/// Calls <see cref="NativeMethods.CloseHandle" /> to release this user token.
/// </summary>
/// <returns><c>true</c> if the function succeeds, <c>false otherwise</c>. To get extended
/// error information, call <see cref="Marshal.GetLastWin32Error"/>.</returns>
protected override bool ReleaseHandle()
{
return NativeMethods.CloseHandle(this.handle);
}
}
/// <summary>
/// A wrapper around a pointer to an array of Unicode strings (LPWSTR*) using a contiguous block of
/// memory that can be freed by a single call to LocalFree.
/// </summary>
public sealed class SafeLocalAllocWStrArray : SafeLocalAllocArray<string>
{
/// <summary>
/// Creates a new SafeLocalAllocWStrArray. This constructor should only be called by P/Invoke.
/// </summary>
private SafeLocalAllocWStrArray()
: base(true)
{
}
/// <summary>
/// Creates a new SafeLocalallocWStrArray to wrap the specified array.
/// </summary>
/// <param name="handle">The pointer to the unmanaged array to wrap.</param>
/// <param name="ownHandle"><c>true</c> to release the array when this object
/// is disposed or finalized, <c>false</c> otherwise.</param>
public SafeLocalAllocWStrArray(IntPtr handle, bool ownHandle)
: base(ownHandle)
{
this.SetHandle(handle);
}
/// <summary>
/// Returns the Unicode string referred to by an unmanaged pointer in the wrapped array.
/// </summary>
/// <param name="index">The index of the value to retrieve.</param>
/// <returns>the value at the position specified by <paramref name="index" /> as a string.</returns>
protected override string GetArrayValue(int index)
{
return Marshal.PtrToStringUni(Marshal.ReadIntPtr(this.handle + IntPtr.Size * index));
}
}
// This class is similar to the built-in SafeBuffer class. Major differences are:
// 1. This class is less safe because it does not implicitly know the length of the array it wraps.
// 2. The array is read-only.
// 3. The type parameter is not limited to value types.
/// <summary>
/// Wraps a pointer to an unmanaged array of objects that can be freed by calling LocalFree.
/// </summary>
/// <typeparam name="T">The type of the objects in the array.</typeparam>
public abstract class SafeLocalAllocArray<T> : SafeHandleZeroOrMinusOneIsInvalid
{
/// <summary>
/// Creates a new SafeLocalArray which specifies that the array should be freed when this
/// object is disposed or finalized.
/// <param name="ownsHandle"><c>true</c> to reliably release the handle during the finalization phase;
/// <c>false</c> to prevent reliable release (not recommended).</param>
/// </summary>
protected SafeLocalAllocArray(bool ownsHandle)
: base(ownsHandle)
{
}
/// <summary>
/// Converts the unmanaged object referred to by <paramref name="valuePointer" /> to a managed object
/// of type T.
/// </summary>
/// <param name="index">The index of the value to retrieve.</param>
/// <returns>the value at the position specified by <paramref name="index" /> as a managed object of
/// type T.</returns>
protected abstract T GetArrayValue(int index);
//
/// <summary>
/// Frees the wrapped array by calling LocalFree.
/// </summary>
/// <returns><c>true</c> if the call to LocalFree succeeds, <c>false</c> if the call fails.</returns>
protected override bool ReleaseHandle()
{
return (NativeMethods.LocalFree(this.handle) == IntPtr.Zero);
}
/// <summary>
/// Copies the unmanaged array to the specified managed array.
///
/// It is important that the length of <paramref name="array"/> be less than or equal to the length of
/// the unmanaged array wrapped by this object. If it is not, at best garbage will be read and at worst
/// an exception of type <see cref="AccessViolationException" /> will be thrown.
/// </summary>
/// <param name="array">The managed array to copy the unmanaged values to.</param>
/// <exception cref="ObjectDisposedException">The unmanaged array wrapped by this object has been
/// freed.</exception>
/// <exception cref="InvalidOperationException">The pointer to the unmanaged array wrapped by this object
/// is invalid.</exception>
/// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
public void CopyTo(T[] array)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
this.CopyTo(array, 0, array.Length);
}
/// <summary>
/// Copies the unmanaged array to the specified managed array.
///
/// It is important that <paramref name="length" /> be less than or equal to the length of
/// the array wrapped by this object. If it is not, at best garbage will be read and at worst
/// an exception of type <see cref="AccessViolationException" /> will be thrown.
/// </summary>
/// <param name="array">The managed array to copy the unmanaged values to.</param>
/// <param name="index">The index to start at when copying to <paramref name="array" />.</param>
/// <param name="length">The number of items to copy to <paramref name="array" /></param>
/// <exception cref="ObjectDisposedException">The unmanaged array wrapped by this object has been
/// freed.</exception>
/// <exception cref="InvalidOperationException">The pointer to the unmanaged array wrapped by this object
/// is invalid.</exception>
/// <exception cref="ArgumentNullException"><paramref name="array"/> is null.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than zero.-or-
/// <paramref name="index" /> is greater than the length of <paramref name="array"/>.-or-
/// <paramref name="length"/> is less than zero.</exception>
/// <exception cref="ArgumentException">The sum of <paramref name="index" /> and <paramref name="length" />
/// is greater than the length of <paramref name="array" />.</exception>
public void CopyTo(T[] array, int index, int length)
{
if (this.IsClosed)
{
throw new ObjectDisposedException(this.ToString());
}
if (this.IsInvalid)
{
throw new InvalidOperationException("This object's buffer is invalid.");
}
if (array == null)
{
throw new ArgumentNullException("array");
}
if (index < 0 || array.Length < index)
{
throw new ArgumentOutOfRangeException("index", "index must be a nonnegative integer that is less than array's length.");
}
if (length < 0)
{
throw new ArgumentOutOfRangeException("length", "length must be a nonnegative integer.");
}
if (array.Length < index + length)
{
throw new ArgumentException("length", "length is greater than the number of elements from index to the end of array.");
}
for (int i = 0; i < length; ++i)
{
array[index + i] = this.GetArrayValue(i);
}
}
}
/// <summary>
/// The type of logon operation to perform.
/// </summary>
internal enum LogonType : uint
{
LOGON32_LOGON_BATCH = 1,
LOGON32_LOGON_INTERACTIVE = 2,
LOGON32_LOGON_NETWORK = 3,
LOGON32_LOGON_NETWORK_CLEARTEXT = 4,
LOGON32_LOGON_NEW_CREDENTIALS = 5,
LOGON32_LOGON_SERVICE = 6,
LOGON32_LOGON_UNLOCK = 7
}
/// <summary>
/// The logon provider to use.
/// </summary>
internal enum LogonProvider : uint
{
LOGON32_PROVIDER_DEFAULT = 0,
LOGON32_PROVIDER_WINNT50 = 1,
LOGON32_PROVIDER_WINNT40 = 2
}
}
Another way of looking at it: with SafeHandle, you should almost never need to write another finalizer.
I think MSDN is pretty clear in definition:
The SafeHandle class provides critical
finalization of handle resources,
preventing handles from being
reclaimed prematurely by garbage
collection and from being recycled by
Windows to reference unintended
unmanaged objects. Before the .NET
Framework version 2.0, all operating
system handles could only be
encapsulated in the IntPtr managed
wrapper object.
The SafeHandle class contains a
finalizer that ensures that the handle
is closed and is guaranteed to run,
even during unexpected AppDomain
unloads when a host may not trust the
consistency of the state of the
AppDomain.
For more information about the
benefits of using a SafeHandle, see
Safe Handles and Critical
Finalization.
This class is abstract because you
cannot create a generic handle. To
implement SafeHandle, you must create
a derived class. To create SafeHandle
derived classes, you must know how to
create and free an operating system
handle. This process is different for
different handle types because some
use CloseHandle, while others use more
specific methods such as
UnmapViewOfFile or FindClose. For this
reason, you must create a derived
class of SafeHandle for each operating
system handle type; such as
MySafeRegistryHandle,
MySafeFileHandle, and
MySpecialSafeFileHandle. Some of these
derived classes are prewritten and
provided for you in the
Microsoft.Win32.SafeHandles namespace.