2017-04-13 120 views
1

我读过的引用类型都使用相同的构造类:C# - 构造类类型的对象

泛型引用类型有所不同的工作。第一次使用任何引用类型构造泛型类型时,运行时创建一个专用泛型类型,其中的对象引用代替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处理类型对象的创建不同的构造类型,即使有是不是“真正的”专门实例化? 有没有办法直接看到什么是和不是由CLR生成的?

+0

*类型*仍然非常明显。文本试图说出的内容(它可以以更清晰的方式进行,而且其中有许多其他不好的写法)是用于实现这些类型的实际代码可以为所有具有引用类型的实例共享。不过,这是一个实现细节,通常对程序员来说很少关注。你需要连接一个调试器并检查jitted代码来看看这个;我不确定C#级别有什么方法可以验证这一点。 –

回答

2

这是否意味着即使没有“真正的”专用实例化,CLR也会为不同的构造类型创建Type对象?

是的。考虑运行时类型检查是该语言的重要组成部分。

var x = new List<string>() as List<object>; 

这应该初始化xnull。如果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>.fG<string>.fG<A>.fG<B>.f具有相同的方法处理,但G<C>.fG<D>.fG<E>.fG<int>.f都有不同的。即使是G<E>.fG<int>.f分享执行。

+0

为了完整性(或作为读者的练习),您可以验证'G '与其他参考类型共享它的实现,而'G '与参考类型或'G '共享实现。 –

+0

@JeroenMostert感谢您的建议,补充,以及其他一些情况。 – hvd

-1

Type对象提供了一个高级抽象类型的信息,并告诉你什么类型是逻辑上的,而泛型的实现是一个低层次的细节,你不应该依赖它。实施细节可以随时更改。

T<A>T<B>是两种不同的类型,因此它们必须被描述为不同的Type对象。这是因为Type对象不仅产生关于T<>的信息,而且产生关于AB的信息,即关于泛型类型参数。 2种类型共享相同的代码库的事实没有区别。

Type对象属于API。你可以在你的代码中使用这些信息。将来可能会扩展该类以反映该语言的新功能,但这不是一个重大改变。

当您想要编写高效的代码时,了解实现细节是很好的。一些低级工具(O/R映射器,编码器等);但是,有时候取决于实施细节。

+0

有用的建议,但不是问题的答案。有时候你想深入实现细节。 –