动态(C#4)和var之间有什么区别?

Iva*_*nov 192 c# dynamic

我已经阅读了大量有关C#v4附带的新关键字的文章,但我无法弄清楚"动态"和"var"之间的区别.

这篇文章让我思考它,但我仍然看不出任何区别.

难道你只能将"var"用作局部变量,而是局部变量和全局变量吗?

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

Mar*_*ell 442

var是静态类型 - 编译器和运行时知道类型 - 它们只是为您节省一些输入...以下是100%相同:

var s = "abc";
Console.WriteLine(s.Length);
Run Code Online (Sandbox Code Playgroud)

string s = "abc";
Console.WriteLine(s.Length);
Run Code Online (Sandbox Code Playgroud)

所有发生的事情是编译器发现s必须是一个字符串(来自初始化器).在这两种情况下,它都知道(在IL中)这s.Length意味着(实例)string.Length属性.

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

dynamic s = "abc";
Console.WriteLine(s.Length);
Run Code Online (Sandbox Code Playgroud)

在这里,s输入为动态.它不知道string.Length,因为它不知道任何有关s在编译时.例如,以下将编译(但不运行):

dynamic s = "abc";
Console.WriteLine(s.FlibbleBananaSnowball);
Run Code Online (Sandbox Code Playgroud)

在运行时(只),它会检查FlibbleBananaSnowball属性-无法找到它,并在火花淋浴爆炸.

使用dynamic,属性/方法/运算符/等在运行时根据实际对象进行解析.非常方便与COM(可以具有仅运行时属性),DLR或其他动态系统(如javascript.

  • 当您在Visual Studio中悬停`var`关键字时,将显示正在推断的实际类型.显示在编译时已知类型. (4认同)
  • 一个有趣的问题是,是否存在静态声明的类的动态祖先.示例:class X {public int Y {get; set;}} dynamic(X)s = GetSpecialX(); 调用字符串test = sY; 会生成编译器错误,因为编译器知道Y但字符串test2 = sZ编译正常并在运行时检查.我能想到这种半动态课程的很多价值! (3认同)

HVS*_*HVS 56

var声明的变量是隐式但静态类型的.使用dynamic声明的变量是动态类型的.此功能已添加到CLR中,以支持Ruby和Python等动态语言.

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


小智 41

我将解释dynamicvar之间的区别.

dynamic d1;
d1 = 1;
d1 = "http://mycodelogic.com";
Run Code Online (Sandbox Code Playgroud)

这会奏效.编译器可以重新创建动态变量的类型.
首先它将类型创建为整数,然后编译器将类型重新创建为字符串,
但在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 
Run Code Online (Sandbox Code Playgroud)


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


ser*_*0ne 14

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你编译这个并用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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以做的最好的事情就是给自己写一个像这样的小控制台应用程序,然后用ILSpy自己测试一下.


小智 12

一个很大的区别 - 您可以拥有动态返回类型.

dynamic Foo(int x)
{
    dynamic result;

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

    return result;
}
Run Code Online (Sandbox Code Playgroud)


小智 10

这是一个简单的例子,它展示了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.
Run Code Online (Sandbox Code Playgroud)

湿婆玛米迪

  • 我的印象是代码示例中"**"字符的存在仅用于表示强调,并不打算成为实际工作代码的一部分. (2认同)

gim*_*mel 7

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

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


Shi*_*ala 5

这是一个不错的 YouTube 视频,通过实际演示讨论了varVS。Dynamic

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

Var 是早期绑定(静态检查),而动态是后期绑定(动态评估)。

var 关键字查看右侧数据,然后在编译时决定左侧数据类型。换句话说,var 关键字可以节省您输入很多内容。看一下下图,当我们给出字符串数据和 x 变量时,我的工具提示中会显示字符串数据类型。

在此输入图像描述

另一方面,dynamic 关键字的目的完全不同。动态对象在运行时进行评估。例如,在下面的代码中,“Length”属性是否存在会在运行时进行评估。我故意输入了一个小“l”,因此该程序编译得很好,但当它实际执行时,当“length”属性存在时,它会抛出错误被称为(小“l”)。

在此输入图像描述