我读过所有引用类型都使用相同的构造类:
泛型对参考类型的工作方式有所不同。第一次使用任何引用类型构造泛型类型时,运行时会创建一个专用泛型类型,其中对象引用将替换MSIL中的参数。然后,每次构造类型以引用类型作为其参数进行实例化时,无论它是什么类型,运行时都会重用先前创建的泛型类型的专用版本。这是可能的,因为所有引用都是相同的大小。 (Generics in the Run Time (C# Programming Guide))
但是,当基于具有不同类型参数的相同泛型对构造对象调用GetType()时,会收到两种不同的类型。其中A和B都是类,而RefType是通用的:
RefType<A> a = new RefType<A>();
RefType<B> b = new RefType<B>();
Console.WriteLine("a type is "+a.GetType());
Console.WriteLine("b type is "+b.GetType());
结果:
"a type is RefType`1[A]"
"b type is RefType`1[B]"
这是否意味着CLR处理为不同构造类型创建Type对象,即使没有&#34; real&#34;专门的实例化? 有没有办法直接看到CLR生成什么和不是什么?
答案 0 :(得分:2)
这是否意味着即使没有“真正的”专用实例化,CLR也会为不同的构造类型处理Type对象的创建?
是。考虑运行时类型检查是该语言的重要部分。
var x = new List<string>() as List<object>;
这应该初始化x
到null
。如果new List<string>()
的运行时类型信息以某种方式丢失了泛型类型参数,则无法使用。
有没有办法直接查看CLR生成和不生成的内容?
class G<T> { public void f() { } }
class A { }
class B { }
struct C { }
struct D { }
enum E : int { }
static void Main(string[] args)
{
Console.WriteLine(typeof(G<object>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<string>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<A>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<B>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<C>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<D>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<E>).GetMethod("f").MethodHandle.Value);
Console.WriteLine(typeof(G<int>).GetMethod("f").MethodHandle.Value);
}
您会看到G<object>.f
,G<string>.f
,G<A>.f
和G<B>.f
具有相同的方法句柄,但G<C>.f
,G<D>.f
,{ {1}}和G<E>.f
都有不同的内容。甚至G<int>.f
和G<E>.f
都没有共享实施。
答案 1 :(得分:-1)
Type
对象以高抽象级别提供类型信息,并在逻辑上告诉您类型的类型,而泛型的实现是一个低级别的细节,您不应该依赖它。实施细节总是可以改变。
T<A>
和T<B>
是两种不同的类型,因此它们必须由不同的Type
对象描述。这是因为Type
对象不仅会生成T<>
的信息,还会生成A
或B
的信息,即通用类型参数。这两种类型共享相同代码库的事实没有区别。
Type
个对象属于API。您可以在代码中使用此信息。 Type
类可能会在将来扩展以反映该语言的新功能,但这不是一个重大变化。
当您想要编写有效的代码时,了解实现细节是很好的。一些低级工具(O / R-mappers,代码编织器等);但是,有时确实依赖于实施细节。