如果尝试使用以下方法创建一个通用结构[StructLayout http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute.aspx(LayoutKind http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.layoutkind.aspx.Explicit)]
属性,使用该结构会在运行时生成异常:
System.TypeLoadException:无法从程序集“bar”加载类型“foo”,因为泛型类型不能具有显式布局。
我一直很难找到任何证据证明这种限制确实存在。这Type.IsExplicitLayout http://msdn.microsoft.com/en-us/library/system.type.isexplicitlayout.aspx文档强烈暗示这是允许和支持的。有谁知道为什么这是不允许的?我想不出任何原因为什么泛型类型会使其难以验证。在我看来,这是一个边缘案例,他们根本就懒得去实施。
Here's 一个例子 http://pastebin.com/ZSz37Cu6为什么显式通用布局很有用:
public struct TaggedUnion<T1,T2>
{
public TaggedUnion(T1 value) { _union=new _Union{Type1=value}; _id=1; }
public TaggedUnion(T2 value) { _union=new _Union{Type2=value}; _id=2; }
public T1 Type1 { get{ if(_id!=1)_TypeError(1); return _union.Type1; } set{ _union.Type1=value; _id=1; } }
public T2 Type2 { get{ if(_id!=2)_TypeError(2); return _union.Type2; } set{ _union.Type2=value; _id=2; } }
public static explicit operator T1(TaggedUnion<T1,T2> value) { return value.Type1; }
public static explicit operator T2(TaggedUnion<T1,T2> value) { return value.Type2; }
public static implicit operator TaggedUnion<T1,T2>(T1 value) { return new TaggedUnion<T1,T2>(value); }
public static implicit operator TaggedUnion<T1,T2>(T2 value) { return new TaggedUnion<T1,T2>(value); }
public byte Tag {get{ return _id; }}
public Type GetUnionType() {switch(_id){ case 1:return typeof(T1); case 2:return typeof(T2); default:return typeof(void); }}
_Union _union;
byte _id;
void _TypeError(byte id) { throw new InvalidCastException(/* todo */); }
[StructLayout(LayoutKind.Explicit)]
struct _Union
{
[FieldOffset(0)] public T1 Type1;
[FieldOffset(0)] public T2 Type2;
}
}
usage:
TaggedUnion<int, double> foo = 1;
Debug.Assert(foo.GetUnionType() == typeof(int));
foo = 1.0;
Debug.Assert(foo.GetUnionType() == typeof(double));
double bar = (double) foo;
Edit:
需要明确的是,请注意,即使结构不是通用的,布局也不会在编译时进行验证。 CLR 在运行时检测引用重叠和 x64 差异:http://pastebin.com/4RZ6dZ3S http://pastebin.com/4RZ6dZ3S我问为什么当检查是在运行时以任何一种方式完成时泛型受到限制。