在C#中有三种“通用”类型(虽然不是所有都是真正的类型):object、var和dynamic。
强调:object是一种类型。一个对象可以是object类型,并且该类型具有其方法,例如ToString()。由于所有类型都直接或间接继承自object,因此一切都可以向上转型为object。当你将一个对象分配给一个object引用时,就像将一个Elephant类型对象分配给一个Animal引用一样,其中Elephant从Animal继承而来,你正在进行向上转型。
SomeType x = new SomeType();
object obj = x;
obj.DoSomething();
- obj在编译时被视为类型object,并且在运行时将是object类型(这是合理的,因为它是一个实际类型-obj声明为object,因此只能是该类型)。
- obj.DoSomething()将导致编译时错误,因为object没有此方法,无论SomeType是否有该方法。
Var
这不是一个实际的类型,它仅仅是"编译器,请根据赋值右侧的类型来推断出类型"的简写。
SomeType x = new SomeType();
var obj = x;
obj.DoSomething();
- obj 在编译时被处理为 SomeType 类型,在运行时也将是 SomeType 类型,就好像你写了 "SomeType" 而不是 "var" 一样。
- 如果 SomeType 有一个方法 DoSomething(),则此代码将正常运行
- 如果 SomeType 没有该方法,则代码将导致编译时错误
动态类型(Dynamic)
这是一种类型,告诉编译器在变量上禁用编译时类型检查。对象在编译时和运行时都被视为具有类型 dynamic。
SomeType x = new SomeType();
dynamic obj = x;
obj.DoSomething();
public void f(dynamic x)
{
x.DoSomething();
}
如果
x的类型没有
DoSomething方法,代码将抛出异常。但是仍然可以调用它并将任何对象作为参数传递而不会在编译时出现错误,这可能导致在运行时显示错误,并可能仅在特定情况下发生 - 可能存在潜在的错误。因此,如果您在类的任何公共接口中使用动态语言,您应该始终使用反射手动进行类型检查,小心处理异常或者根本不这样做。
注意:所引用的对象类型从未更改。虽然obj可能是object,但它所引用的x 仍然是SomeType。
ISomeMarkerInterface
不好吗? - yamenISomeMarkerInterface
不是很好,因为(也许只有我这样),但我在将其强制转换回实际对象以执行任何有用操作时遇到了问题。由于标记接口没有属性或方法,所以在LINQ lambda表达式中使用它非常困难:\ - Jason