List vs List

我需要创建一个异构的对象List (自定义类)。 我的第一个想法是创建一个List但我很快就知道这不是我想要的。 我的下一个想法是List ,这似乎不是一个坏主意。 但是,我正在做一些研究,并且遇到了关于装箱和拆箱的这篇文章。在这个例子中,他们基本上都在做我想要的List

除了dynamic将在运行时和Object在编译时进行评估这一事实外, ListList之间有什么区别? 它们本质上不一样吗?

C#中有3种“通用”类型(尽管不是全部都是真实类型):object,var和dynamic。

宾语

实际类型,与任何其他类型一样,具有一个特殊规则:如果类型不inheritance,则它inheritance自object 。 由此可见, 所有类型都直接或间接地从对象inheritance。

重点: 对象是一种类型 。 对象可以是object类型,类型有其方法,如ToString()。 由于一切都从对象inheritance,所以一切都可以转化为对象 。 当您将对象分配给对象引用时,您正在进行向上转换,就像将Elephant类型对象分配给Elephantinheritance自AnimalAnimal引用一样。

 SomeType x = new SomeType(); object obj = x; obj.DoSomething(); 
  • obj在编译时被视为类型为object的对象 ,并且在运行时将是object类型(这是逻辑的,因为它是一个实际类型 – obj被声明为object,因此只能是该类型)
  • obj.DoSomething()将导致编译时错误,因为对象没有此方法,无论SomeType是否具有它。

瓦尔

这不是一个实际的类型,它只是“编译器的简写,根据赋值的右侧为我找出类型”。

 SomeType x = new SomeType(); var obj = x; obj.DoSomething(); 
  • obj在编译时被视为SomeType类型,并且在运行时将是SomeType类型,就像您编写了“SomeType”而不是“var”一样。
  • 如果SomeType有一个方法DoSomething() ,这个代码将起作用
  • 如果SomeType没有该方法,则代码将导致编译时错误

动态

这是一种告诉编译器禁止对变量进行编译时类型检查的类型。 在编译时和运行时将对象视为具有动态类型。

 SomeType x = new SomeType(); dynamic obj = x; obj.DoSomething(); 
  • obj在编译和运行时是动态类型
  • 如果SomeType有一个方法DoSomething() ,这个代码将起作用
  • 如果SomeType没有该方法,代码将编译,但在运行时抛出exception
  • 请注意,如果不小心使用动态可能会非常容易导致exception:

     public void f(dynamic x) { x.DoSomething(); } 

如果x是没有DoSomething方法的类型,这将抛出exception,但是仍然可以调用它并将任何对象作为参数传递而没有编译时错误,导致只显示自身的错误在运行时,可能只在特定情况下 – 一个潜在的错误。 因此,如果您在类的任何类型的公共接口中使用dynamic,则应始终使用reflection在运行时手动键入 – 检查,小心处理exception,或者不首先执行此操作。

注意:当然,被引用的对象永远不会改变它的类型。 虽然obj可能是对象 ,但它引用的x仍然是SomeType

不同之处在于,如果您使用对象并尝试访问对象的某个成员,则会出现编译时错误(因为对象没有此成员)。 为了工作,您需要知道类型是什么并投射它。

使用动态,您可以访问任何成员 – 没有编译时错误。 如果成员在运行时不存在,那将是运行时错误。 如果您知道您的所有对象都具有相同的成员,那么这就是要走的路。

但是,如果是这种情况,还有另一个更明确的解决方案:您可以使用此成员定义一个接口,然后使所有您的同等对象实现它,您的列表可以是List

请记住,动态的性能可能稍微差一些,因为动态类型分辨率很好。