C# - 键入构造类的对象

时间:2017-04-13 15:54:56

标签: c# generics types

我读过所有引用类型都使用相同的构造类:

  

泛型对参考类型的工作方式有所不同。第一次使用任何引用类型构造泛型类型时,运行时会创建一个专用泛型类型,其中对象引用将替换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生成什么和不是什么?

2 个答案:

答案 0 :(得分: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>.f,{ {1}}和G<E>.f都有不同的内容。甚至G<int>.fG<E>.f都没有共享实施。

答案 1 :(得分:-1)

Type对象以高抽象级别提供类型信息,并在逻辑上告诉您类型的类型,而泛型的实现是一个低级别的细节,您不应该依赖它。实施细节总是可以改变。

T<A>T<B>是两种不同的类型,因此它们必须由不同的Type对象描述。这是因为Type对象不仅会生成T<>的信息,还会生成AB的信息,即通用类型参数。这两种类型共享相同代码库的事实没有区别。

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

当您想要编写有效的代码时,了解实现细节是很好的。一些低级工具(O / R-mappers,代码编织器等);但是,有时确实依赖于实施细节。