В чем разница между dynamic (C # 4) и var? - PullRequest
191 голосов
/ 07 июня 2009

Я прочитал тонну статей об этом новом ключевом слове, которое поставляется с C # v4, но я не мог понять разницу между "dynamic" и "var".

Эта статья заставила меня задуматься, но я все еще не вижу никакой разницы.

Возможно ли, что вы можете использовать "var" только как локальную переменную, но динамическую как локальную, так и глобальную?

Не могли бы вы показать код без динамического ключевого слова, а затем показать тот же код с динамическим ключевым словом?

Ответы [ 14 ]

438 голосов
/ 07 июня 2009

var имеет статическую типизацию - компилятор и среда выполнения знают тип - они просто экономят время при наборе текста ... 100% идентичны:

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

и

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

Все, что произошло, было то, что компилятор выяснил, что s должна быть строкой (из инициализатора). В обоих случаях он знает (в IL), что s.Length означает свойство (instance) 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.

56 голосов
/ 07 июня 2009

Переменные, объявленные с var , неявно, но статически . Переменные, объявленные с dynamic , вводятся динамически. Эта возможность была добавлена ​​в CLR для поддержки динамических языков, таких как Ruby и Python.

Я должен добавить, что это означает, что динамические объявления разрешаются во время выполнения, var объявления разрешаются во время компиляции.

39 голосов
/ 04 июля 2012

Я собираюсь объяснить разницу между динамическим и переменным .

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

Это будет работать. Компилятор может воссоздать тип переменной dynamic .
сначала он создает тип как integer и после этого компилятор воссоздает тип как string
, но в случае 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.
Компилятор не имеет никакой информации о типе переменной dynamic . таким образом, компилятор не будет показывать какой-либо интеллект.
Компилятор имеет всю информацию о сохраненном значении типа var , поэтому компилятор будет показывать интеллект. Аргумент функции и функция также могут возвращать тип объекта
Но тип
var не может быть передан как аргумент функции, и функция не может возвращать тип объекта. Переменная этого типа может работать в области, где она определена.
14 голосов
/ 29 июня 2012

var означает, что применяется статическая проверка типов (раннее связывание). Динамический подразумевает, что применяется динамическая проверка типов (позднее связывание). С точки зрения кода, учитывайте следующее:

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, вы обнаружите, что компилятор добавил некоторый код поздней привязки, который будет обрабатывать вызов Hello () из b, тогда как ранняя привязка была применена к 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.

12 голосов
/ 14 июня 2013

Одно большое отличие - вы можете иметь динамический тип возврата.

dynamic Foo(int x)
{
    dynamic result;

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

    return result;
}
10 голосов
/ 17 марта 2011

Вот простой пример, который демонстрирует разницу между 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.

Шива Мамиди

7 голосов
/ 07 июня 2009

var это просто сокращение для обычного объявления типа, где вы позволяете компилятору угадать правильный тип.

dynamic - это новый (статический) тип, где все проверки выполняются во время выполнения, а не компилятором.

4 голосов
/ 07 июня 2009

Тип переменной, объявленной с помощью var, определяется компилятором, это ярлык для указания имени типа, ничего более.

Однако динамическое значение определяется во время выполнения, компилятор не имеет представления о фактическом типе, и все обращения к методу / полю / свойству с этой переменной будут выполняться во время выполнения.

3 голосов
/ 01 января 2014

Это - хорошее видео на YouTube, в котором рассказывается о var VS Dynamic с практической демонстрацией.

Ниже приведено более подробное объяснение со снимком.

Var раннее связывание (статическая проверка), в то время как динамическое позднее связывание (динамическая оценка).

Ключевое слово Var просматривает ваши правые данные, а затем во время компиляции решает тип данных слева. Другими словами, ключевое слово var просто спасает вас от набора множества вещей. Посмотрите на изображение ниже, где, когда мы дали строковые данные, а переменная x показывает строковый тип данных в моей подсказке.

enter image description here

С другой стороны, динамическое ключевое слово предназначено для совершенно других целей. Динамические объекты оцениваются во время выполнения. Например, в приведенном ниже коде свойство «Length» существует или не оценивается во время выполнения. Я специально набрал маленькое «l», так что эта программа скомпилировалась нормально, но при ее фактическом выполнении выдает ошибку, когда свойство «length» назывался (МАЛЕНЬКИЙ "l").

enter image description here

2 голосов
/ 21 октября 2013
  1. Var и динамический тип определения.
  2. var во время компиляции, в то время как динамические во время выполнения.
  3. в объявлении и инициализации var являются обязательными, как постоянная переменная, тогда как
  4. в динамической инициализации может быть во время выполнения как переменные только для чтения.
  5. в типе var, какой бы тип не был решен во время инициализации, следующий не может измениться, но
  6. dynamic может принимать любой тип, даже если пользователь определяет тип данных.
...