dynamic(C#4)和var有什么区别?

我已经阅读了大量有关C#v4新增关键字的文章,但我无法弄清楚“dynamic”和“var”之间的区别。

这篇文章让我想起了,但是我仍然看不出有什么不同。

难道你可以只使用“var”作为局部variables,但作为本地和全球dynamic?

对于我的无知,我感到抱歉,但是你能显示一些没有dynamic关键字的代码,然后用dynamic关键字显示相同的代码吗?

var是静态types – 编译器和运行时知道types – 它们只是为您节省一些键入…以下是100%相同的:

 var s = "abc"; Console.WriteLine(s.Length); 

 string s = "abc"; Console.WriteLine(s.Length); 

发生的一切就是编译器发现s必须是一个string(来自初始化程序)。 在这两种情况下,它都知道(在IL中) s.Length是指(实例) string.Length属性。

dynamic是一个非常不同的野兽; 它与object最为相似,但具有dynamic调度:

 dynamic s = "abc"; Console.WriteLine(s.Length); 

这里s被input为dynamic 。 它不知道string.Length ,因为在编译时它不知道s 。 例如,下面的代码可以编译(但不能运行):

 dynamic s = "abc"; Console.WriteLine(s.FlibbleBananaSnowball); 

在运行时(仅),它会检查 FlibbleBananaSnowball属性 – 无法find它,并在火花阵雨中爆炸。

dynamic ,属性/方法/运营商/等在运行时解决,基于实际的对象。 非常方便与COM(可以只有运行时的属性),DLR或其他dynamic系统(如javascript )交谈。

var声明的variables是隐含的,但是是静态types的。 dynamic声明的variables是dynamicinput的。 为了支持Ruby和Python等dynamic语言,这个function被添加到CLR中。

我应该补充一点,这意味着dynamic声明在运行时被parsing, var声明在编译时被parsing。

我将解释dynamicvar之间的区别。

 dynamic d1; d1 = 1; d1 = "http://mycodelogic.com"; 

这将工作。 编译器可以重新创builddynamicvariables的types。
首先它创buildtypes为整数 ,然后编译器将重新创buildtypes为string
但在变种的情况下

 var v1; // Compiler will throw error because we have to initialized at the time of declaration var v2 = 1; // Compiler will create v1 as **integer** v2 = "Suneel Gupta"; // Compiler will throw error because, compiler will not recreate the type of variable 

当使用' var '关键字时,types由编译器在编译时决定,而当使用' dynamic '关键字时,types由运行时决定。


' var '关键字是一个强烈隐含types的局部variables,编译器可以通过它初始化expression式来确定types – 在进行LINQ编程时非常有用。


编译器没有关于variables的dynamictypes的任何信息。 所以编译器不会显示任何的智能。
编译器具有关于vartypes的存储值的所有信息,因此编译器将显示智能。


dynamictypes可以作为函数parameter passing,函数也可以返回对象types

vartypes不能作为函数parameter passing,函数不能返回对象types。 这种types的variables可以在它定义的范围内工作。

var意味着应用静态types检查(早期绑定)。 dynamic意味着应用dynamictypes检查(后期绑定)。 在代码方面,考虑以下几点:

 class Junk { public void Hello() { Console.WriteLine("Hello"); } } class Program { static void Main(String[] args) { var a = new Junk(); dynamic b = new Junk(); a.Hello(); b.Hello(); } } 

如果你编译这个,并用ILSpy检查结果,你会发现编译器已经添加了一些后期绑定代码,它将处理来自b的Hello()调用,而因为早期的绑定被应用于a,a能够调用Hello ()直接。

例如(ILSpy拆卸)

 using System; namespace ConsoleApplication1 { internal class Junk { public void Hello() { Console.WriteLine("Hello"); } } } using Microsoft.CSharp.RuntimeBinder; using System; using System.Runtime.CompilerServices; namespace ConsoleApplication1 { internal class Program { [CompilerGenerated] private static class <Main>o__SiteContainer0 { public static CallSite<Action<CallSite, object>> <>p__Site1; } private static void Main(string[] args) { Junk a = new Junk(); //NOTE: Compiler converted var to Junk object b = new Junk(); //NOTE: Compiler converted dynamic to object a.Hello(); //Already Junk so just call the method. //NOTE: Runtime binding (late binding) implementation added by compiler. if (Program.<Main>o__SiteContainer0.<>p__Site1 == null) { Program.<Main>o__SiteContainer0.<>p__Site1 = CallSite<Action<CallSite, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "Hello", null, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); } Program.<Main>o__SiteContainer0.<>p__Site1.Target(Program.<Main>o__SiteContainer0.<>p__Site1, b); } } } 

你可以做的最好的事情是发现自己的一个小小的控制台应用程序,并用ILSpy自己testing一下。

下面是一个简单的例子,它演示了Dynamic(4.0)和Var之间的区别

 dynamic di = 20; dynamic ds = "sadlfk"; var vi = 10; var vsTemp= "sdklf"; Console.WriteLine(di.GetType().ToString()); //Prints System.Int32 Console.WriteLine(ds.GetType().ToString()); //Prints System.String Console.WriteLine(vi.GetType().ToString()); //Prints System.Int32 Console.WriteLine(vsTemp.GetType().ToString()); //Prints System.String **ds = 12;** //ds is treated as string until this stmt now assigning integer. Console.WriteLine(ds.GetType().ToString()); **//Prints System.Int32** **vs = 12**; //*Gives compile time error* - Here is the difference between Var and Dynamic. var is compile time bound variable. 

湿婆Mamidi

一个很大的区别 – 你可以有一个dynamic的返回types。

 dynamic Foo(int x) { dynamic result; if (x < 5) result = x; else result = x.ToString(); return result; } 

var只是一个正常types声明的简写,让编译器猜测正确的types。

dynamic是一种新的(静态)types,所有的检查都是在运行时完成的,而不是由编译器完成的。

用var声明的variables的types由编译器决定,它是指定types名称的快捷方式,仅此而已。

但是,dynamic是在运行时确定的,编译器不知道实际的types,所有的方法/字段/属性访问与该variables将在运行时计算出来。

这是一个很好的youtubevideo,谈谈关于var VS Dynamic的实际演示。

以下是有关快照的更详细的解释。

Var是早绑定(静态检查),而dynamic是迟绑定(dynamic评估)。

Var关键字查看右侧的数据,然后在编译期间决定左侧的数据types。换句话说,var关键字只会节省您input大量的东西。 看看下面的图片,当我们给了string数据和xvariables显示string数据types在我的工具提示。

在这里输入图像描述

另一方面,dynamic关键字是完全不同的目的。 dynamic对象在运行时进行评估。 例如在下面的代码中,“Length”属性是否存在于运行时期间被评估。我故意input了一个小的“l”,所以这个程序编译得很好,但是当它实际执行的时候,当“length”属性出现错误时被称为(小“l”)。

在这里输入图像描述

dynamicvariables和varvariables都可以存储任何types的值,但是它需要在声明时初始化'var'。

编译器没有关于“dynamic”typesvariables的任何信息。 var是编译器安全的,即编译器有关于存储值的所有信息,所以它在运行时不会引起任何问题。

dynamictypes可以作为函数parameter passing,函数也可以返回它。 Vartypes不能作为函数parameter passing,函数不能返回对象types。 这种types的variables可以在它定义的范围内工作。

在dynamic的情况下,Casting不是必须的,但是你需要知道与存储types有关的属性和方法,而对于var,由于编译器具有执行操作的所有信息,所以不需要进行转换。

dynamic:在使用reflection或dynamic语言支持或使用COM对象进行编码时很有用,因为我们需要编写较less的代码量。

var:从linq查询中获取结果时很有用。 在3.5框架中介绍支持linqfunction。

参考: Counsellingbyabhi

  1. Var和dynamic定义types。
  2. var在编译时dynamic运行时。
  3. 在var声明和初始化中都是像常量variables一样强制的
  4. 在dynamic初始化时可以像运行时只读variables一样。
  5. 在vartypes中,无论什么types在初始化的时候都是决定不了的
  6. dynamic也可以采用任何types,即使用户也定义了数据types。

不要混淆dynamic和var。 使用var声明局部variables只是一个语法快捷方式,编译器会从expression式中推断特定的数据types。 var关键字只能用于在方法内声明局部variables,而dynamic关键字可用于局部variables,字段和参数。 您无法将expression式转换为var,但可以将expression式转换为dynamicexpression式。 您必须显式初始化使用var声明的variables,而不必初始化用dynamic声明的variables。

  1. Var(隐式types局部variables)关键字用于定义局部variables。在Var的情况下,基础数据types是在编译时根据初始赋值确定的。一旦初始赋值已经用Vartypes进行,那么它将变成强types。​​如果你试图用Vartypes存储任何不兼容的值,将会导致编译时错误。

例:

 Var strNameList=new List<string>(); By using this statement we can store list of names in the string format. strNameList.add("Senthil"); strNameList.add("Vignesh"); strNameList.add(45); // This statement will cause the compile time error. 

但是在dynamictypes中,底层types只在运行时才被确定。dynamic数据types在编译时不被检查,也不是强types的。我们可以为dynamictypes分配任何初始值,然后它可以被重新分配给任何新的在其生命周期中的价值。

例:

 dynamic test="Senthil"; Console.Writeline(test.GetType()) // System.String test=1222; Console.Writeline(test.GetType()) // System.Int32 test=new List<string>(); Console.Writeline(test.GetType()) //System.Collections.Generic.List'1[System.String] 

它也不提供IntelliSense支持。当我们使用linq的时候也不会给予更好的支持。因为它不支持lambdaexpression式,扩展方法和匿名方法。

这里是区别

  • var是静态types的(编译时),dynamic是dynamictypes的(运行时)

  • 声明为var的variables只能在本地使用,dynamicvariables可以作为parameter passing给函数(函数签名可以将param定义为dynamic但不是var)。

  • dynamic的属性的解决scheme发生在运行时,而不是与var的情况下,这意味着在编译时任何variables声明为dynamic可以调用一个可能或不可能存在的方法,所以编译器不会抛出一个错误。

  • types铸造与var不可能,但与dynamic可能(你可以将一个对象作为dynamic而不是var)。

阿伦Vijayraghavan