dynamic (c# 4)和var之间的区别是什么?

我已经阅读了大量关于c# v4附带的新关键字的文章,但我无法区分“dynamic”和“var”之间的区别。

这篇文章让我思考,但我仍然看不到任何不同。

你是否只能将“var”用作局部变量,但同时用作局部变量和全局变量?

你能显示一些代码没有动态关键字,然后显示相同的代码与动态关键字吗?

90669 次浏览

var声明的变量是隐式的,但是是静态类型的。用动态声明的变量是动态类型的。CLR添加此功能是为了支持Ruby和Python等动态语言。

我应该补充一点,这意味着动态声明在运行时解析,var声明在编译时解析。

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的类型是作为动态。它不知道string.Length,因为它在编译时不知道任何东西关于s。例如,下面的代码也可以编译(但不能运行):

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

在运行时(仅),它将为FlibbleBananaSnowball属性检查 -未能找到它,并在火花阵雨中爆炸。

使用dynamic,属性/方法/操作符等将基于实际对象解析为在运行时。非常方便地与COM(可以具有仅运行时属性)、DLR或其他动态系统(如javascript)通信。

var只是普通类型声明的简写,让编译器猜测正确的类型。

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

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

然而动态是在运行时确定的,编译器不知道实际的类型,所有对该变量的方法/字段/属性访问都将在运行时计算出来。

下面是一个简单的例子,演示了动态(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和var。 使用var声明局部变量只是一种语法上的快捷方式,可以让编译器从表达式推断出特定的数据类型。 关键字var只能用于在方法中声明局部变量,而dynamic关键字可以用于局部变量、字段和参数。不能将表达式强制转换为var,但可以将表达式强制转换为dynamic。必须显式地初始化使用var声明的变量,而不必初始化使用dynamic声明的变量

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之间的区别。

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 '关键字时,类型由编译器在编译时决定,而当使用' 动态 '关键字时,类型由运行时决定。
` var `关键字,一个强隐式类型的局部变量,编译器能够从初始化表达式中确定其类型——在进行LINQ编程时非常有用。 编译器没有关于变量动态类型的任何信息。
编译器有关于var类型存储值的所有信息,因此编译器将显示智能。
动态类型可以作为函数参数传递,函数也可以返回对象类型
但是
var类型不能作为函数参数传递,函数不能返回对象类型。这种类型的变量可以在其定义的范围内工作。 < /引用> < / p >

动态变量和var变量都可以存储任何类型的值,但需要在声明时初始化'var'。

编译器没有关于变量的“动态”类型的任何信息。 Var是编译器安全的,即编译器拥有关于存储值的所有信息,因此它在运行时不会引起任何问题

动态类型可以作为函数参数传递,函数也可以返回它。 Var类型不能作为函数参数传递,函数不能返回对象类型。此类型的变量可以在其定义的作用域内工作

在动态类型转换的情况下,不需要,但你需要知道与存储类型相关的属性和方法,而对于var不需要类型转换,因为编译器有执行操作的所有信息。

dynamic:在使用反射或动态语言支持或COM对象编码时很有用,因为我们需要编写更少的代码。

var:在从linq查询中获取结果时有用。在3.5框架中引入了对linq特性的支持。

参考:Counsellingbyabhi

  1. Var(隐式类型局部变量)关键字用于定义局部变量。对于Var,底层数据类型是在编译时根据初始赋值确定的。一旦使用Var类型进行了初始赋值,那么它将成为强类型。如果您试图存储与Var类型不兼容的值,则会导致编译时错误。

例子:

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]

它也不提供智能感知支持。当我们使用linq工作时,它也没有提供更好的支持。因为它不支持lambda表达式、扩展方法和匿名方法。

一个很大的不同——你可以有一个动态返回类型。

dynamic Foo(int x)
{
dynamic result;


if (x < 5)
result = x;
else
result = x.ToString();


return result;
}

区别就在这里

  • Var是静态类型(编译时),dynamic是动态类型(运行时)

  • 声明为var的变量只能在局部动态使用 变量可以作为参数传递给函数(函数签名

  • 与动态属性的解析发生在运行时和 这不是var的情况,它意味着在编译时任何变量 声明为dynamic可以调用一个可能存在也可能不存在的方法 因此编译器不会抛出错误

  • 使用var的类型转换是不可能的,但使用动态的类型转换是可能的(你可以将一个对象转换为动态的,而不是var的类型转换)。

阿伦Vijayraghavan

  1. Var和dynamic定义类型。
  2. Var在编译时,而dynamic在运行时。
  3. 在var声明和初始化中,两者都是强制性的,就像常量变量while一样
  4. 在动态初始化可以在运行时像只读变量。
  5. 在var类型中,无论什么类型都是在初始化时确定的,但不能更改下一步
  6. 动态可以采用任何类型,甚至用户定义的数据类型。

它讨论了varDynamic的实际演示。

下面是一个更详细的快照解释。

Var是早期绑定(静态检查),而dynamic是后期绑定(动态计算)。

Var关键字查看右边的数据,然后在编译时决定左边的数据类型。换句话说,var关键字节省了你输入很多东西。看看下面的图像,当我们给出字符串数据和x变量显示字符串数据类型在我的工具提示。

enter image description here

另一方面,动态关键字的目的完全不同。动态对象在运行时计算。例如,在下面的代码中,“长度”;属性是否存在将在运行时计算。我故意打了一个小的“l",所以这个程序编译良好,但当它实际执行时,它抛出了一个错误,当"财产被称为(SMALL "l")。

enter image description here