2009-06-07 196 views
171

Había leído un montón de artículos sobre esa nueva palabra clave que se enviará con C# v4, pero no pude distinguir la diferencia entre un "dinámico" y "var".¿Cuál es la diferencia entre dynamic (C# 4) y var?

This article me hizo pensar en ello, pero todavía no puedo ver ninguna diferencia.

¿Es que puede usar "var" solo como una variable local, pero dinámica como local y global?

Disculpa mi ignorancia, pero ¿podrías mostrar algún código sin palabra clave dinámica y luego mostrar el mismo código con la palabra clave dinámica?

Respuesta

408

var se escribe estática - el compilador y el tiempo de ejecución saben el tipo - que acaba de ahorrar algo de tecleo ... los siguientes son 100% idénticos:

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

y

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

Todo lo que sucedió fue que el compilador descubrió que s debe ser una cadena (desde el inicializador). En ambos casos, sabe (en la IL) que s.Length significa la propiedad (instancia) string.Length.

dynamic es un muy diferente bestia; es muy similar a object, pero con distribución dinámica:

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

Aquí, s se escribe tan dinámico. No sabe acerca de string.Length, porque no sabe nada sobre s en tiempo de compilación. Por ejemplo, la siguiente sería compilar (pero no de ejecución) también:

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

En tiempo de ejecución (solamente), lo haría cheque para la propiedad FlibbleBananaSnowball - no logran encontrarlo, y explotar en una lluvia de chispas.

Con dynamic, las propiedades/métodos/operadores/etc se resuelven en el tiempo de ejecución, en función del objeto real. Muy útil para hablar con COM (que puede tener propiedades solo de tiempo de ejecución), DLR u otros sistemas dinámicos, como javascript.

+135

Si tan sólo pudiera dar otro 1 para la propiedad FlibbleBananaSnowball ... :-) – Joey

+3

Una cuestión interesante sería si hay ancestros dinámicos de clases declaradas estáticamente. Ejemplo: clase X {public int Y {get; set;}} dynamic (X) s = GetSpecialX(); Llamada prueba de cadena = s.Y; generaría un error de compilación porque el compilador conoce Y pero string test2 = s.Z compilaría bien y se verificaría en tiempo de ejecución. ¡Podría pensar en mucho valor de tales clases semidinámicas! – mmmmmmmm

+0

@rstevens - IIRC, puede agregar comportamiento dinámico a través de una interfaz (aunque no hay soporte de lenguaje directo para implementar tipos dinámicos en C#, solo consumiéndolos), así que esto no es poco realista ... oh, la diversión que podríamos tener; -p –

54

Las variables declaradas con var están implícitamente pero estáticamente mecanografiado. Las variables declaradas con dynamic se escriben de forma dinámica. Esta capacidad se agregó al CLR para admitir lenguajes dinámicos como Ruby y Python.

Debo añadir que esto significa que dinámicas declaraciones se resuelven en tiempo de ejecución, var declaraciones se resuelven en tiempo de compilación.

+7

+1 Por razones de concisión –

+1

1 saber por qué se agregó, el misterio revelado – GenEric35

7

var es solo una abreviatura de una declaración de tipo normal, donde se deja que el compilador adivine el tipo correcto.

dynamic es un tipo nuevo (estático), donde todas las comprobaciones se realizan en tiempo de ejecución, no por el compilador.

4

El tipo de una variable declarada con var está determinada por el compilador, es un atajo para especificar el nombre del tipo, nada más.

Sin embargo, dinámico se determina en tiempo de ejecución, el compilador no tiene idea del tipo real y todos los accesos de método/campo/propiedad con esa variable se resolverán en tiempo de ejecución.

9

aquí es simple ejemplo que demuestra la diferencia entre Dinámico (4.0) y 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. 

Shiva Mamidi

+2

Mi impresión es que la presencia de caracteres '**' en el ejemplo del código está destinada a indicar únicamente el énfasis y no pretende ser parte del código de trabajo real. – DavidRR

1

no hay que confundir dinámico y var. Declarar una variable local usando var es simplemente un atajo sintáctico que hace que el compilador infiera el tipo de datos específico de una expresión. La palabra clave var se puede usar solo para declarar variables locales dentro de un método, mientras que la palabra clave dinámica se puede usar para variables locales, campos y argumentos. No puede convertir una expresión en var, pero puede convertir una expresión en dinámica. Debe inicializar explícitamente una variable declarada utilizando var, mientras que no tiene que inicializar una variable declarada con dynamic.

14

var implica que se aplica la comprobación de tipo estático (vinculación anticipada). dinámico implica que se aplica la comprobación dinámica de tipos (enlace tardío). En términos del código, condsider lo siguiente:

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(); 
    } 
} 

Si compila esta e inspeccionar los resultados con ILSpy, se encuentra que el compilador ha añadido algo de código enlace en tiempo que se encargará de la llamada a Hola() desde b, mientras que debido a que el enlace temprano se aplicó a a, a es capaz de llamar a Hello() directamente.

p. Ej. (ILSpy desmontaje)

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); 
     } 
    } 
} 

Lo mejor que puede hacer para descubrir la diferencia es a escribir una pequeña aplicación de consola como éste, y poner a prueba usted mismo con ILSpy.

+0

gran ejemplo básico de cómo IL trata a ambos después de la compilación. Gracias. – Kings

35

Voy a explicar la diferencia entre dinámico y var.

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

Esto funcionará. el compilador puede volver a crear el tipo de variable dinámica.
primero se crean tipo que número entero y después de que el compilador recreará tipo que cadena
pero en caso de 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 


Cuando se utiliza el ' var' palabra clave, el tipo de es decidido por el compilador en tiempo de compilación, mientras que cuando se usa la palabra clave ' dynamic', el tipo de ejecución es decidido por el tiempo de ejecución.
' var' variable local implícitamente tipada para la cual el compilador puede determinar el tipo de la expresión de inicialización, muy útil cuando se hace la programación LINQ.
El compilador no tiene ninguna información sobre tipo de variable dinámica. entonces el compilador no mostrará ninguna inteligencia.
compilador tiene toda la información sobre el valor almacenado de var tipo por lo que el compilador mostrará la inteligencia.
tipo dinámico se puede pasar como argumento de función y la función también puede devolver el tipo de objeto
Pero
var tipo no se puede pasar como argumento de función y la función no puede devolver el tipo de objeto. Este tipo de variable puede funcionar en el ámbito donde se define.

2

variables dinámicas y var pueden almacenar cualquier tipo de valor, pero es necesario para inicializar 'var' en el momento de la declaración.

compilador no tiene ninguna información acerca del tipo 'dinámico' de la variable. var es seguro para el compilador, es decir, el compilador tiene toda la información sobre el valor almacenado, para que no cause ningún problema en tiempo de ejecución.

tipo dinámico se puede pasar como argumento de la función y la función también puede devolverlo. El tipo Var no se puede pasar como argumento de función y la función no puede devolver el tipo de objeto. Este tipo de variable puede funcionar en el ámbito donde se define.

En caso de Fundición dinámica no se requiere, pero lo que necesita saber la propiedad y métodos relacionados con el tipo almacenado, mientras que para var No hay necesidad de emitir porque compilador tiene toda la información para realizar la operación.

dinámica: Útil cuando se codifica utilizando la reflexión o soporte de lenguajes dinámicos o con los objetos COM, porque requerimos a escribir menos cantidad de código.

var: Útil para obtener el resultado de las consultas de linq. En el marco 3.5 introduce la función de soporte linq.

Referencia: Counsellingbyabhi

1
  1. El Var palabra clave (local mecanografiado implícito variable) se utiliza para definir caso local variables.In de Var, el tipo de datos subyacente se determina al mismo tiempo de compilación basado en la asignación inicial. Una vez que la asignación inicial se ha realizado con el tipo Var, se convertirá en un tipo fuerte. Si intenta almacenar cualquier valor incompatible con el tipo Var, se producirá un error de tiempo de compilación.

Ejemplo:

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. 

Pero en el tipo dinámico, el tipo subyacente se determina sólo durante la ejecución time.Dynamic tipo de datos no se comprueba en tiempo de compilación y también que no es fuertemente typed.We puede asignar cualquier valor inicial para el tipo dinámico y luego puede reasignarse a cualquier valor nuevo durante su tiempo de vida.

Ejemplo:

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] 

No proporciona compatibilidad con IntelliSense also.It no da un mejor apoyo cuando nos damos trabajo con LINQ también.Porque no admite expresiones lambda, métodos de extensión y métodos anónimos.

10

Una gran diferencia: puede tener un tipo de devolución dinámica.

dynamic Foo(int x) 
{ 
    dynamic result; 

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

    return result; 
} 
1

Estas son las diferencias

  • var es de tipo estático (tiempo de compilación), dinámica se escribe de forma dinámica (en tiempo de ejecución)

  • Una variable declarada como var sólo se puede utilizar localmente , las variables dinámicas se pueden pasar como parámetros a la función (la firma de función puede definir un parámetro como dinámico pero no var).

  • con dinámica la resolución de las propiedades que ocurre en tiempo de ejecución y eso no es el caso de var que significa en tiempo de compilación cualquier variable declarada como dinámica puede llamar a un método que puede o maynot existir y lo que el compilador no quisiste lanzar un error

  • No es posible la conversión de var con var pero con dinámica (se puede convertir un objeto en dinámico pero no en var).

Arun Vijayraghavan

2
  1. Var y dinámica definen tipo.
  2. var en el tiempo de compilación mientras dinámico están en tiempo de ejecución.
  3. en la declaración var y la inicialización son obligatorios como variable constante, mientras que
  4. en inicialización dinámica pueden estar en tiempo de ejecución como variables de solo lectura.
  5. en var tipo de cualquier tipo que se decida en el momento de la inicialización no puede cambiar a continuación pero
  6. dinámico puede adoptar cualquier tipo, incluso el usuario definir el tipo de datos también.
3

This es un video de youtube bonita que habla de var VS Dynamic con demostración práctica.

A continuación hay una explicación más detallada con la instantánea.

El Var se enlaza temprano (estático comprobado) mientras que el dinámico se agota tarde (se evalúa dinámicamente).

La palabra clave Var mira los datos del lado derecho y luego durante el tiempo de compilación decide el tipo de datos de la mano izquierda. En otras palabras, la palabra clave var te ahorra escribir muchas cosas. Eche un vistazo a la imagen de abajo donde, cuando hemos dado datos de cadena y la variable x muestra el tipo de datos de cadena en mi información sobre herramientas.

enter image description here

Por otra parte dinámica de palabras clave es para fines completamente diferentes. Los objetos dinámicos se evalúan durante el tiempo de ejecución. Por ejemplo, en el siguiente código, la propiedad "Longitud" existe o no se evalúa durante el tiempo de ejecución.He escrito a propósito una pequeña "l", por lo que este programa compiló bien, pero cuando realmente se ejecutó, arrojó un error cuando se llamó a la propiedad "length" (SMALL "l").

enter image description here

Cuestiones relacionadas