C#中的很多关键词用法比较容易混淆,var和dynamic就是其中一组,但其实它们是有本质的区别的。
Var是C# 3中引入的,var本身并不是一种类型,其实它仅仅只是一个语法糖,它要求编译器根据一个表达式推断具体的数据类型,变量实际的类型是编译时所赋值得类型。var声明的变量在赋值的那一刻,就已经决定了它是什么类型,所以Var类型的变量在初始化时候,必须提供初始化的值。
比如:
所以如果你这样使用,就会有编译错误:
var a = 1;
a = "Test";
用Var声明的变量是隐式的,但是是静态类型的。
dynamic更新,因为它是C# 4.0中引入的新类型,它的特点是申明为dynamic类型的变量,不是在编译时候确定实际类型的, 而是在运行时。用dynamic声明的变量是动态类型的。这个功能被添加到CLR中,以支持动态语言,比如Ruby和Python。
这意味着动态声明是在运行时解析的,而Var声明是在编译时解析的。而dynamic被编译后,实际是一个 object类型,只不过编译器会对dynamic类型进行特殊处理,让它在编译期间不进行任何的类型检查,而是将类型检查放到了运行期。
所以下面的代码是能够通过编译的,但是会在运行时报错:
dynamic a = "test";
a++;
所以下面的代码是能够通过编译的,但是会在运行时报错:
上面代码内部处理的过程是怎样的呢?
首先, dynamic类型赋值为字符串"test", 运行++操作的时候,.net会去寻找当前的赋值类型string中是否支持++操作,发现不支持,出现异常。
所以,如果这样修改一下,就可以让代码正常运行起来
dynamic a = "test";
a = 1;
a++;
有了dynamic,.net就以及有了动态类型的优势,但是由于对于dynamic类型的所有操作,都是在运行时确定的,所有错误无法在编译时候出现,使用的时候,就需要非常小心。
因为dynamic是类型,所以如果函数接受的是确定类型的参数,是不能传入dynamic类型的,这样会有编译错误。
var | dynamic |
---|---|
在c# 3.0中引入的 | 在c# 4.0中引入的 |
静态类型这意味着声明的变量类型由编译器在编译时决定。 | 动态类型这意味着变量的类型是由编译器在运行时决定的。 |
需要在声明时进行初始化, var str= " I am a string ";查看分配给变量str的值,编译器将把变量str视为字符串。 | 声明时不需要初始化 dynamic str; str=”I am a string”; //Works fine and compiles str=2; //Works fine and compiles |
在编译时能够捕获错误。因为编译器在编译时就知道类型以及类型的方法和属性 | 当编译器在运行时发现类型、类型的方法和属性时,会在运行时捕获错误。 |
Visual Studio显示智能感知,因为分配给编译器的变量类型是已知的。 | Visual Studio智能感知不可用,因为类型及其相关方法和属性只能在运行时知道 |
例如, var obj1; 将抛出一个编译错误,因为变量没有初始化。编译器需要初始化这个变量,以便从值中推断类型。 | 例如, dynamic obj1; 可成功编译,不会报错。 |
比如: var obj1=1; will compile var obj1=” I am a string”; 将会抛出一个错误。因为当值1被赋给obj1时,编译器已经确定obj1的类型是System.Int32,现在给它分配一个字符串值违反了类型安全。 | 比如: dynamic obj1=1; 将编译成功接着, dynamic obj1=” I am a string”; 将编译并运行,因为编译器将为obj1创建System.Int32。然后,当赋值为“I am string”时,将类型重新创建为字符串。这段代码可以很好地工作。 |