remarks example cref c# .net dynamic anonymous-types

c# - example - Tipo anónimo vs tipo dinámico



remarks c# (6)

¿Cuáles son las diferencias reales entre el tipo anónimo (var) en c # 3.0 y el tipo dinámico (dinámico) que viene en c # 4.0?


El tipo dynamic es esencialmente object , pero resolverá todas las llamadas al método / propiedad / operador, etc. en tiempo de ejecución a través del DLR u otro proveedor (como la reflexión).

Esto se parece mucho a VB con Option Strict Off , y lo hace muy versátil para llamar a COM o a tipos de DLR.

No hay comprobación de tipos en tiempo de compilación con dinámica; por así decirlo, los tipos anónimos son bestias propias de tipo estático y verificadas por tipos (se pueden ver en el reflector, aunque no son bonitas).

Además, los tipos anónimos pueden manejarse exclusivamente por el compilador; dynamic requiere una gran compatibilidad con el tiempo de ejecución, por lo que los tipos anónimos son una característica de C #, pero la dynamic implementará en gran medida .NET 4.0 (con algo de compatibilidad con C # 4.0).


Hay tres veces, con tres actores, uno en cada ocasión.

  • Tiempo de diseño - programador
  • Tiempo de compilación - compilador c #
  • Tiempo de ejecución: tiempo de ejecución .net

Los tipos anónimos son declarados y nombrados por el compilador. Esta declaración se basa en las especificaciones del programador (cómo utilizó el tipo). Dado que estos tipos reciben el nombre después de que el programador abandonó el proceso, parecen ser anónimos para el programador, por lo tanto, "anónimos".

  • El programador dice: algún tipo tiene un nombre y una dirección
  • El compilador dice: Hay un tipo llamado xyz con propiedades y campos de Nombre y Dirección, ambas cadenas.
  • el tiempo de ejecución dice: No puedo decir ninguna diferencia entre xyz y cualquier tipo que el programador haya hecho.

La escritura dinámica en c # le permite llamar a métodos que pueden o no existir en el momento de la compilación. Esto es útil para llamar a python o javascript, que no están compilados.

  • El programador dice: trate esta instancia de un automóvil como un tipo dinámico. Ahora, curandero.
  • El compilador dice: tipado dinámico ¿eh? debe estar bien. No me quejaré porque no puedo verificarlo.
  • El tiempo de ejecución intenta hacer la instancia de coche, charlatanería.


Nada como un pequeño código para aclarar las cosas:

// anonymous types var anonType = new {Id = "123123123", Name = "Goku", Age = 30, DateAdded = new DateTime()}; // notice we have a strongly typed anonymous class we can access the properties with Console.WriteLine($"Anonymous Type: {anonType.Id} {anonType.Name} {anonType.Age} {anonType.DateAdded}"); // compile time error //anonType = 100; // dynamic types dynamic dynType = 100.01m; Console.WriteLine($"Dynamic type: {dynType}"); // it''s ok to change the type however you want dynType = new List<DateTime>(); Console.WriteLine($"Dynamic type: {dynType}"); // mix dynamic and anonymous dynamic dynamicAnonymousType = new {Id = 8000, FirstName = "Goku", Gender = "male", IsSuperSaiyan = true}; // Wasn''t sure this would work but it does! However, you lose intellisense on the FirstName so you have to type it manually. Console.WriteLine($"FirstName: {dynamicAnonymousType.FirstName}"); dynamicAnonymousType = 100; Console.WriteLine(dynamicAnonymousType); // runtime error Console.WriteLine($"Id: {dynamicAnonymousType.FirstName}");


Parece que estás mezclando tres cosas ortogonales completamente diferentes:

  • tipeo estático vs. dinámico
  • tipaje manifiesto vs. implícito
  • nombrado contra tipos anónimos

Esos tres aspectos son completamente independientes, no tienen nada que ver el uno con el otro.

La tipificación estática frente a la dinámica se refiere a cuándo tiene lugar la verificación de tipos: la escritura dinámica tiene lugar en el tiempo de ejecución , la tipificación estática tiene lugar antes del tiempo de ejecución .

La tipificación implícita frente a la implícita se refiere a si los tipos se manifiestan en el código fuente o no: el tipado manifiesto significa que el programador debe escribir los tipos en el código fuente, la tipificación implícita significa que el sistema de tipos los descifra por sí mismo.

Los tipos nominales y anónimos se refieren a, bueno, si los tipos tienen nombres o no.

La palabra clave dynamic en C # 4.0 significa que esta variable, parámetro, método, campo, propiedad ... lo que sea que esté escrito dinámicamente , es decir, que su tipo será verificado en tiempo de ejecución. Todo lo que no está escrito como dinámico está escrito estáticamente. El hecho de que un tipo sea estático o dinámico no solo determina cuándo se realiza la comprobación de tipos, sino también en C # 4.0 cuando se produce el envío del método . En C #, el despacho del método se realiza antes del tiempo de ejecución, basado en el tipo estático (a excepción del polimorfismo del subtipo en tiempo de ejecución), mientras que en objetos de tipo dinámico en C # 4.0, el despacho del método se realiza en tiempo de ejecución, en función del tipo de tiempo de ejecución.

La palabra clave var en C # 3.0 significa que esta variable local se escribirá implícitamente , es decir, que en lugar de que el programador escriba explícitamente el tipo, el sistema de tipo lo resolverá por sí mismo. Esto no tiene nada que ver con la escritura dinámica, al menos en C # 3.0. La variable se escribirá fuertemente estáticamente como si hubiera escrito el tipo usted mismo. Es simplemente una conveniencia: por ejemplo, ¿por qué tendría que escribir todos los nombres de tipo dos veces en HashMap<int, string> foo = new HashMap<int, string>(); cuando el sistema de tipos puede deducir claramente que foo es un HashMap<int, string> , entonces en su lugar escribes var foo = new HashMap<int, string(); . Tenga en cuenta que no hay nada dinámico o anónimo acerca de esto. El tipo es estático y tiene un nombre: HashMap<int, string> . Por supuesto, en C # 4.0, si el sistema de tipos se da cuenta de que el lado derecho de la tarea es dinámico, entonces el tipo de la variable en el lado izquierdo será dinámico.

Un tipo anónimo en C # 3.0 significa que este tipo no tiene nombre. Bueno, en realidad, los tipos anónimos reales habrían requerido un cambio incompatible con el Sistema de tipo común, por lo que lo que sucede detrás del telón es que el compilador generará un nombre muy largo, muy aleatorio, único e ilegal para el tipo y se colocará ese nombre en donde aparezca el tipo anónimo. Pero desde el punto de vista del programador, el tipo no tiene nombre. ¿Por qué es esto útil? Bueno, a veces tienes resultados intermedios que solo necesitas brevemente y luego tirar de nuevo. Darles a esos tipos transitorios un nombre propio los elevaría a un nivel de importancia que simplemente no merecen. Pero, de nuevo, no hay nada dinámico en esto.

Entonces, si el tipo no tiene nombre, ¿cómo puede el programador referirse a él? Bueno, ella no puede! Al menos no directamente. Lo que el programador puede hacer es describir el tipo: tiene dos propiedades, una llamada "nombre" de tipo string , la otra llamada "id" de tipo int . Ese es el tipo que quiero, pero no me importa cómo se llame.

Aquí es donde las piezas comienzan a unirse. En C #, debe declarar los tipos de variables locales anotando explícitamente los nombres de los tipos. Pero, ¿cómo se puede escribir el nombre de un tipo que no tiene nombre? Aquí es donde entra var : porque desde C # 3.0, esto ya no es verdad: ya no tienes que escribir los nombres, también puedes decirle al compilador que lo resuelva. Por lo tanto, aunque lo que escribí en el primer párrafo anterior es cierto, que el tipeo implícito y los tipos anónimos no tienen nada que ver con los demás, también es cierto que los tipos anónimos serían bastante inútiles sin tipeo implícito.

Sin embargo, tenga en cuenta que lo opuesto no es cierto: la tipificación implícita es perfectamente útil sin tipos anónimos. var foo = HashMap<int, string> tiene mucho sentido y no hay ningún tipo anónimo a la vista.


Un tipo anónimo es un tipo real generado por el compilador creado para usted. Lo bueno de esto es que el compilador puede reutilizar este tipo más tarde para otras operaciones que lo requieran ya que es un POCO.

Mi comprensión de los tipos dinámicos es que están vinculados de forma tardía, lo que significa que CLR (o DLR) evaluará el objeto en el momento de la ejecución y luego utilizará pato para permitir o no permitir el acceso de los miembros al objeto.

Así que supongo que la diferencia es que los tipos anónimos son verdaderos POCO que el compilador puede ver, pero que solo puede usar y los tipos dinámicos son los objetos dinámicos con destino tardío.