When is a value type / reference type constraint useful in C#?
I'm looking for simple examples that demonstrate when the value type / reference type 开发者_运维问答constraints are useful.
... where T : struct // when is this useful?
... where T : class // and what about this?
I remember seeing some very nice examples in the past but I just can't find them.
It allows you to use as
operator on T if it is T:class
.
It forbids you to compare T with null
if T is T:struct
.
Note that if you omit T:class
then you can compare T to null even when T is a value type.
[Note: I needed to edit this post a few times before it got correct. At least I hope it is now correct.]
The primary usefulness that I've found in it lies with Marshalling and pinning the object in memory.
For example, I do a lot of work with internal structures that can't be auto-converted, or are sent down the wire as a byte stream, so I wrote this helper:
public static T PinAndCast<T>(this Array o) where T : struct
{
var handle = System.Runtime.InteropServices.GCHandle.Alloc(o, GCHandleType.Pinned);
T result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return result;
}
"T : class" will force the generic type specified to be a class, not a value. For example, we can make up an ObjectList class that requires the generic type specified to be a class, not a value:
class ObjectList<T> where T : class {
...
}
class SomeObject { ... }
ObjectList<int> invalidList = new ObjectList<int>(); //compiler error
ObjectList<SomeObject> someObjectList = new ObjectList<SomeObject>(); //this works
This forces an invariant on your generic type T that otherwise might not be enforceable. "T : struct" would work the same way. Note that you can also use this construct to enforce not only that the type T is a class, but also that it matches an interface. The code sample I took this from also has
class MyList<T> where T : class, IEntity { ... }
which forces T to be a class AND also be an IEntity.
精彩评论