我已经阅读了大量关于c# v4附带的新关键字的文章,但我无法区分“dynamic”和“var”之间的区别。
这篇文章让我思考了一下,但我还是看不出有什么不同。
你是否只能将“var”用作局部变量,但同时用作局部变量和全局变量?
你能显示一些代码没有动态关键字,然后显示相同的代码与动态关键字吗?
我已经阅读了大量关于c# v4附带的新关键字的文章,但我无法区分“dynamic”和“var”之间的区别。
这篇文章让我思考了一下,但我还是看不出有什么不同。
你是否只能将“var”用作局部变量,但同时用作局部变量和全局变量?
你能显示一些代码没有动态关键字,然后显示相同的代码与动态关键字吗?
当前回答
用var声明的变量是隐式的,但是是静态类型的。使用dynamic声明的变量是动态类型的。CLR添加此功能是为了支持Ruby和Python等动态语言。
我应该补充一点,这意味着动态声明在运行时解析,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自己测试它。
Var是静态类型的——编译器和运行时知道它的类型——它们只是为你节省了一些输入…以下是100%相同的:
var s = "abc";
Console.WriteLine(s.Length);
and
string s = "abc";
Console.WriteLine(s.Length);
所发生的一切只是编译器发现s必须是一个字符串(来自初始化式)。在这两种情况下,它都知道(在IL中)s.l end意味着(实例)字符串。长度属性。
动态是一种非常不同的野兽;它与object最相似,但具有动态调度:
dynamic s = "abc";
Console.WriteLine(s.Length);
这里,s的类型是动态的。它不知道字符串。长度,因为它在编译时不知道s的任何信息。例如,下面的代码也可以编译(但不能运行):
dynamic s = "abc";
Console.WriteLine(s.FlibbleBananaSnowball);
在运行时(仅),它将检查flibb黎巴嫩asnowball属性-未能找到它,并爆炸在一个火花淋浴。
使用dynamic,属性/方法/操作符等在运行时根据实际对象解析。非常方便地与COM(可以具有仅运行时属性)、DLR或其他动态系统(如javascript)通信。
这是一个很好的youtube视频,讨论了var VS动态与实际演示。
下面是一个更详细的快照解释。
Var是早期绑定(静态检查),而dynamic是后期绑定(动态计算)。
Var关键字查看右边的数据,然后在编译时决定左边的数据类型。换句话说,var关键字节省了你输入很多东西。看看下面的图像,当我们给出字符串数据和x变量显示字符串数据类型在我的工具提示。
另一方面,动态关键字的目的完全不同。动态对象在运行时计算。例如,在下面的代码中,“长度”属性是否存在将在运行时计算。我故意输入了一个小的“l”,所以这个程序编译良好,但当它实际执行时,当“length”属性被调用时抛出了一个错误(small“l”)。
下面是一个简单的例子,演示了动态(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
用var声明的变量的类型是由编译器决定的,它是指定类型名称的快捷方式,仅此而已。
然而动态是在运行时确定的,编译器不知道实际的类型,所有对该变量的方法/字段/属性访问都将在运行时计算出来。