我已经阅读了很多有关C#v4附带的新关键字的文章,但是我看不出“ dynamic”和“ var”之间的区别。
这篇文章让我考虑了一下,但是我仍然看不到任何区别。
您是否只能将“ var”用作局部变量,但可以同时用作局部变量和全局变量?
您能显示一些没有动态关键字的代码,然后再显示具有动态关键字的相同代码吗?
我已经阅读了很多有关C#v4附带的新关键字的文章,但是我看不出“ dynamic”和“ var”之间的区别。
这篇文章让我考虑了一下,但是我仍然看不到任何区别。
您是否只能将“ var”用作局部变量,但可以同时用作局部变量和全局变量?
您能显示一些没有动态关键字的代码,然后再显示具有动态关键字的相同代码吗?
Answers:
var
是静态类型的-编译器和运行时知道类型-它们只是为您节省了一些键入内容...以下内容是100%相同的:
var s = "abc";
Console.WriteLine(s.Length);
和
string s = "abc";
Console.WriteLine(s.Length);
发生的所有事情是编译器发现它s
必须是一个字符串(来自初始化程序)。在这两种情况下,它都知道(在IL中)s.Length
意味着(实例)string.Length
属性。
dynamic
是完全不同的野兽;它与最为相似object
,但是具有动态分配功能:
dynamic s = "abc";
Console.WriteLine(s.Length);
在这里,s
键入为dynamic。它不知道string.Length
,因为它不知道任何有关s
在编译时。例如,以下代码也将编译(但不运行):
dynamic s = "abc";
Console.WriteLine(s.FlibbleBananaSnowball);
在运行时(仅),它将检查该FlibbleBananaSnowball
属性-找不到它,并在火花中爆炸。
使用dynamic
,可以在运行时根据实际对象解析属性/方法/运算符/等。与COM(可以具有仅运行时属性),DLR或其他动态系统(例如)交谈非常方便javascript
。
var
可能会推断出由于子类型和隐式强制转换而可能不需要的类型,但这很重要。也就是说,var
可能在隐式强制转换发生时解决了与预期静态不同的类型(最明显的是更通用的类型,但不限于此)。一个简单的例子是object x = ""
vs. var x = ""
vs. var x = "" as object
,但是其他更狡猾(更现实)的情况也可能发生,并且可能导致细微的错误。
WriteLine
哪一个。这种“绑定”发生在编译时。在with的情况下dynamic
,的类型.Length
也必须是dynamic
,并且直到运行时才确定哪个重载(如果有的话)WriteLine
最合适。绑定在运行时发生。
var
在Visual Studio中时,将显示正在推断的实际类型。向您显示该类型在编译时是已知的。
我将解释dynamic和var之间的区别。
dynamic d1;
d1 = 1;
d1 = "http://mycodelogic.com";
这将起作用。编译器可以重新创建动态变量的类型。
首先,它将类型创建为整数,然后该编译器将重新创建类型为字符串,
但是对于var
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 '关键字时,类型由编译器在编译时确定,而使用' dynamic '关键字时,类型由运行时确定。
' var '关键字,一个强隐式类型化的局部变量,编译器可以通过该变量来从初始化表达式确定类型-在进行LINQ编程时非常有用。
编译器没有有关变量动态类型的任何信息。因此编译器将不会显示任何智能。
编译器具有有关var 类型存储值的所有信息,因此编译器将显示智能。
动态类型可以作为函数参数传递,函数也可以返回对象类型,
但是
var类型不能作为函数参数传递,并且函数不能返回对象类型。这种类型的变量可以在其定义的范围内工作。
var表示已应用静态类型检查(早期绑定)。dynamic表示应用了动态类型检查(后期绑定)。就代码而言,请考虑以下内容:
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对其进行测试。
这是一个简单的示例,展示了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.
湿婆玛米迪
**
代码示例中字符的存在仅用于表示重点,而不是真正的工作代码的一部分。
这是一个不错的youtube视频,其中通过实际演示谈论了var
VS。Dynamic
以下是快照的详细说明。
Var早期绑定(静态检查),而dynamic后期绑定(动态评估)。
var关键字查看您的右侧数据,然后在编译时决定左侧数据的类型。换句话说,var关键字可以节省您键入许多内容。看下面的图片,当我们给定字符串数据并且x变量在我的工具提示中显示字符串数据类型时。
另一方面,dynamic关键字用于完全不同的目的。动态对象在运行时进行评估。例如,在下面的代码中,运行时会评估“ Length”属性是否存在。我特意键入了一个小“ l”,因此该程序编译良好,但是当其实际执行时,当“ length”属性出现错误被称为(小“ l”)。
动态变量和var变量都可以存储任何类型的值,但在声明时需要初始化'var'。
编译器没有有关变量“动态”类型的任何信息。var是编译器安全的,即编译器具有关于存储值的所有信息,因此在运行时不会引起任何问题。
动态类型可以作为函数参数传递,函数也可以返回它。变量类型不能作为函数参数传递,函数不能返回对象类型。这种类型的变量可以在其定义的范围内工作。
在不需要动态转换的情况下,但您需要了解与存储类型有关的属性和方法,而对于var则不需要转换,因为编译器具有执行操作的所有信息。
动态的:当使用反射或动态语言支持或使用COM对象进行编码时很有用,因为我们需要编写更少的代码。
var:从linq查询中获取结果时很有用。它在3.5框架中介绍了支持linq功能。
例:
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.
但是在动态类型中,基础类型仅在运行时确定。动态数据类型在编译时不检查,也不是强类型的。我们可以为动态类型分配任何初始值,然后可以将其重新分配给任何新值一生中的价值。
例:
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时,它也没有提供更好的支持。因为它不支持lambda表达式,扩展方法和匿名方法。
这是差异
var是静态类型的(编译时),dynamic是动态类型的(运行时)
声明为var的变量只能在本地使用,动态变量可以作为参数传递给函数(函数签名可以将参数定义为dynamic而不是var)。
如果使用动态,则属性解析将在运行时发生,而使用var则不是这样,这意味着在编译时,任何声明为动态的变量都可以调用可能存在或不存在的方法,因此编译器不会引发错误。
使用var进行类型转换是不可能的,但使用动态转换是可能的(可以将对象转换为动态而不是var)。
阿伦(Arun Vijayraghavan)