List vs List
我需要创建一个异构的对象List
(自定义类)。 我的第一个想法是创建一个List
但我很快就知道这不是我想要的。 我的下一个想法是List
,这似乎不是一个坏主意。 但是,我正在做一些研究,并且遇到了关于装箱和拆箱的这篇文章。在这个例子中,他们基本上都在做我想要的List
。
除了dynamic
将在运行时和Object
在编译时进行评估这一事实外, List
和List
之间有什么区别? 它们本质上不一样吗?
C#中有3种“通用”类型(尽管不是全部都是真实类型):object,var和dynamic。
宾语
实际类型,与任何其他类型一样,具有一个特殊规则:如果类型不inheritance,则它inheritance自object 。 由此可见, 所有类型都直接或间接地从对象inheritance。
重点: 对象是一种类型 。 对象可以是object类型,类型有其方法,如ToString()。 由于一切都从对象inheritance,所以一切都可以转化为对象 。 当您将对象分配给对象引用时,您正在进行向上转换,就像将Elephant类型对象分配给Elephantinheritance自Animal的Animal引用一样。
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
。
请记住,动态的性能可能稍微差一些,因为动态类型分辨率很好。