2012-04-30 35 views
16

Necesito crear un List heterogéneo de objetos (clases personalizadas). Lo primero que pensé fue crear un List<ISomeMarkerInterface>, pero rápidamente aprendí que esto no es lo que quiero. Mi siguiente pensamiento fue List<dynamic> y esto no parecía ser una mala idea. Sin embargo, estaba investigando un poco y me encontré con este article about boxing and unboxing y en el ejemplo, básicamente están haciendo lo que quiero usando List<Object>.Lista <Object> vs Lista <dynamic>

Aparte del hecho de que dynamic serán evaluados en tiempo de ejecución y Object en tiempo de compilación, ¿cuál es la diferencia entre List<dynamic> y List<Object>? ¿No son esencialmente lo mismo?

+2

¿por qué necesita almacenar objetos heterogéneos en la misma lista? Sólo curiosidad ... –

+0

debes buscar dinámico vs objeto, mira este hilo, probablemente responda tu respuesta http://stackoverflow.com/questions/3442821/dynamic-vs-object-type – Habib

+0

Tengo una clase donde uno de las propiedades es una colección de elementos relevantes para esa clase que no son del mismo tipo, pero son relevantes como grupo. – Jason

Respuesta

19

Hay 3 tipos "generales" (aunque no todos son tipos reales) en C#: object, var y dynamic.

objeto

Un tipo real, al igual que cualquier otro tipo, con una regla especial: si un tipo no hereda, que hereda de objeto. De esto, se deduce que todos los tipos heredan de objeto, directa o indirectamente.

Énfasis: objeto es un tipo. Un objeto puede ser del tipo objeto, y el tipo tiene sus métodos, como ToString(). Dado que todo hereda de objeto, todo puede ser upcast en objeto. Cuando se asigna un objeto a un objeto de referencia, que está haciendo upcasting al igual que cuando se asigna un tipo de objetoelefante a una referencia Animal donde elefante hereda de animal.

SomeType x = new SomeType(); 
object obj = x; 
obj.DoSomething(); 
  • obj se trata como siendo de tipo objeto en tiempo de compilación, y será de tipo objeto en tiempo de ejecución (que es lógico, ya que es un tipo real - obj está declarada como objeto por lo que sólo puede ser de ese tipo)
  • obj.DoSomething() causará un error de tiempo de compilación, como ob ject no tiene este método, independientemente de si SomeType lo tiene.

Var

Esto no es un tipo real, es simplemente la abreviatura de "compilador, averiguar el tipo para mí basado en el lado derecho de la asignación".

SomeType x = new SomeType(); 
var obj = x; 
obj.DoSomething(); 
  • obj es tratado como del tipo SomeType en tiempo de compilación, y será de tipo SomeType en tiempo de ejecución, al igual que si hubiera escrito "SomeType" en lugar de "var" .
  • si SomeType tiene un método HacerAlgo(), este código funcionará
  • si SomeType no tiene el método, el código causará un error en tiempo de compilación

Dinámico

Este es un tipo que le dice al compilador que deshabilite la verificación del tipo en tiempo de compilación en la variable. Se considera que un objeto tiene el tipo dinámico en tiempo de compilación y tiempo de ejecución.

SomeType x = new SomeType(); 
dynamic obj = x; 
obj.DoSomething(); 
  • obj es de tipo dinámico en tiempo de compilación y tiempo de ejecución
  • si SomeType tiene un método HacerAlgo(), este código funciona
  • si SomeType doesn' t tiene el método, el código compilará, pero lanzará una excepción en el tiempo de ejecución
  • no e que dinámico puede causar excepciones muy fácilmente si se utiliza sin cuidado:

    public void f(dynamic x) 
    { 
        x.DoSomething(); 
    } 
    

Esto lanzará una excepción si x es de un tipo que no tiene la método HacerAlgo, pero seguirá siendo posible llamarlo y pasar cualquier objeto como el parámetro sin un error en tiempo de compilación, lo que provoca un error que solo se muestra en el tiempo de ejecución, y posiblemente solo en circunstancias específicas: un posible error. Por lo tanto, si utiliza la dinámica en cualquier clase de interfaz pública de una clase, siempre debe verificar manualmente el tiempo de ejecución utilizando reflectividad, lidiar con excepciones cuidadosamente o no hacerlo en primer lugar.

Nota: el objeto al que se hace referencia nunca cambia su tipo, por supuesto. Mientras obj puede ser objeto, la x que se refiere a es todavía SomeType.

+4

- 1 por decir que 'dynamic' no es un tipo real (muy diferente de' var' que _isn't_ un tipo real, como dices correctamente). 'dynamic' es definitivamente un tipo en C#, incluso es un tipo _static_, pero un objeto de tipo' dynamic' omitirá la comprobación de tipo estático. Consulte la §4.7 de la Especificación del lenguaje C# o este enlace (http://msdn.microsoft.com/en-us/library/dd264736.aspx) para obtener más información. – Nailuj

+0

Vaya, lo arreglé. Debería haber verificado primero, supongo. : D Aunque pensé que la dinámica se resolvió inmediatamente con el tipo apropiado en el tiempo de ejecución de la asignación y en realidad nunca se tipeó como "dinámico", pero aparentemente este no es el caso. – svinja

+1

Ya no -1 :) – Nailuj

2

La diferencia es que si utiliza un objeto e intenta acceder a algún miembro de su objeto, se producirá un error de tiempo de compilación (porque el objeto no tiene este miembro). Para poder trabajar necesitas saber de qué tipo es y emitirlo.

Con dynamic puede acceder a cualquier miembro sin errores de tiempo de compilación. Si el miembro no existe en tiempo de ejecución, sería un error de tiempo de ejecución. Este es el camino a seguir si sabes que tus objetos heredados tienen todos el mismo miembro, por ejemplo.

Sin embargo, si este es el caso, hay otra solución más clara: puede definir una interfaz con este miembro y luego hacer que todos sus objetos heredados la implementen y su lista puede ser List<IYourInterface>.

Tenga en cuenta que el rendimiento de la dinámica puede ser ligeramente peor, debido a la resolución de tipo, así, dinámica.

+0

usando dynamic, ¿puede verificar la existencia de un miembro y continuar si no está allí sin generar un error? tipo de como en Javascript cómo se puede hacer algo como 'if (data.something) {}'? – Jason

+1

Esto se llama reflexión. Puedes usarlo con o sin * dynamic *. Mire en GetType(), GetMethod(), etc. – svinja

+0

+1, si va por la ruta de reflexión, también podría usar Object (pero aún así recomendaría la interfaz del marcador) – MattDavey

Cuestiones relacionadas