2010-02-01 6 views
10

Basado en mi respuesta a this question, quiero comprobar algo en mi comprensión de la próxima dynamic tipo para C# 4.¿Puede el tipo "dinámico" variar de forma segura en una colección genérica <dynamic>?

En este caso, tenemos una colección que representa los campos de un registro extraído de una tabla de base de datos desconocida . El código anterior (pre.Net 4) requiere tales elementos de retención de la colección del tipo Object. Dejando a un lado los méritos de una colección de este tipo, me pregunto qué pasará cuando cambie Object a dynamic.

Por un lado, espero que desde cosas para los tipos dinámicos están resueltos en tiempo de ejecución que todo debe estar muy bien, siempre y cuando el programador no hace ninguna errores tipográficos o errores sobre el tipo esperado de una opción concreta en la colección.

Por otro lado, me pregunto acerca de la palabra "todos" en la oración anterior. ¿Acaso el tiempo de ejecución podría almacenar en caché los resultados desde la primera vez que se accede a una propiedad dinámica, lo que hace que las llamadas posteriores que utilizan diferentes tipos fallen?

Respuesta

3

Aquí hay un poco relevantes desde el blog de Sam que habla brevemente sobre la política de almacenamiento en caché.

http://blogs.msdn.com/samng/archive/2008/10/29/dynamic-in-c.aspx

El DLR comprueba una memoria caché para ver si el acción determinada ya ha sido atado en contra de la actual serie de argumentos. Por lo tanto, en nuestro ejemplo, haríamos un tipo de coincidencia basado en 1, 2 y el tipo de ejecución d. Si tenemos un token de caché, , devolvemos el resultado almacenado en caché. Si no tenemos un golpe de caché, entonces el DLR comprueba si el receptor es un IDynamicObject.Estos tipos son esencialmente objetos que sabe cómo cuidar de su propia unión, tales como objetos COM IDispatch, reales dinámicas objetos como Ruby o Python, los o algún objeto .NET que implementa la interfaz IDynamicObject. Si es alguno de estos, entonces el DLR deshabilita al IDO y le pide que vincule la acción .

Tenga en cuenta que el resultado de invocar el IDO para vincular es un árbol de expresiones que representa el resultado del enlace. Si no es un IDO, entonces el DLR llama al encuadernador de idioma (en nuestro caso , el encuadernador de tiempo de ejecución C#) para enlazar la operación. La carpeta del tiempo de ejecución de C# enlazará la acción y devolverá un árbol de expresiones que representa el resultado del enlace. Una vez que han sucedido los pasos 2 o 3 , el árbol de expresiones resultante se fusiona en el mecanismo de almacenamiento en caché para que cualquier llamada posterior se pueda ejecutar contra la memoria caché en lugar de rebote.

Sin embargo, lo que Sam no menciona es exactamente lo que es la política de falta de caché. Existen dos políticas principales de caché-error: (1) desencadenar una falta de caché cuando cambian los tipos de argumento, (2) desencadenar una falta de caché cuando las identidades de los argumentos cambian.

Obviamente, el primero es mucho más eficiente; Hacer ejercicio cuando podemos caché basado únicamente en el tipo es complicado. Una exégesis detallada de cómo funciona toda esa lógica llevaría bastante tiempo; con suerte, Chris, Sam o yo haremos una publicación en el blog uno de estos días.

+0

Esto es algo de lo que estaba preocupado. En mi ejemplo simple, es bastante fácil para el tiempo de ejecución saber que son tipos diferentes. Pero el almacenamiento en caché sí ocurre, por lo que si tuviera que hacer muchos de estos, podría ser posible encontrar un caso límite. En realidad, sin embargo, no creo que sea un problema para el caso, lo que provocó esta pregunta, que es bueno saber. –

+3

@Joel: Claro, puede haber errores en la política de falta de caché. Si encuentras alguno, házmelo saber! :) –

1

bien, en lugar de esperar por una respuesta que disparó a Visual Studio 2010 Beta 2, y este programa de marchas de prueba, bien:

class Foo 
{ 
    public string foo = "Foo!"; 
} 
class Bar 
{ 
    public int bar = 42; 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var test = new List<dynamic>(); 
     test.Add(new Foo()); 
     test.Add(new Bar()); 

     Console.WriteLine(test[0].foo.Substring(0,3)); 
     Console.WriteLine(test[1].bar.ToString("000")); 

     Console.ReadKey(true); 
    } 
} 

quería asegurarse de que no sólo no puedo comprobar en las propiedades con diferentes nombres, pero que también tenían diferentes tipos y que utilicé funciones en cada tipo que son incompatibles entre sí. Este parece para sugerir que si algo está en caché, el tiempo de ejecución es lo suficientemente inteligente como para saber cuándo usar el caché y cuándo no. Todavía me gustaría saber si alguien conoce un caso extremo en el que esto no se cumple, o un comentario más autoritario sobre por qué lo hará.

1

Puede pensar en azúcar dinámica como solo sintáctica para escribir todas las llamadas a métodos usando Reflection y MethodInfo.Invoke(): debajo del capó no funciona exactamente así, pero se puede pensar que funciona de esa manera , con todas las consideraciones de "llamar a 1000 métodos/seg vía dinámica => incidencia asesinada" que lo acompañan.

+1

"No funciona exactamente así" es una exageración. No funciona * nada en absoluto * así si estás usando la carpeta C#. –

+0

@Eric Bastante, y tiene mucha razón, pero a los efectos de conceptualizar qué tan 'dinámico' funciona, era más fácil dar la explicación de "no respetar la resistencia del viento" –

1

En cuanto a la lista de diccionario / se refiere, se puede ver simplemente object. dynamic está en gran medida en el ojo del espectador, es decir, el llamando al código; debajo del capó es "objeto más un poco de azúcar". Entonces, no deberías ver ningún problema aquí.

Prueba:

static void Main() 
    { 
     Console.WriteLine(IsObject<int>()); // false 
     Console.WriteLine(IsObject<object>()); // true 
     Console.WriteLine(IsObject<dynamic>()); // true 
     Console.WriteLine(IsObject<string>()); // false 
    } 
    static bool IsObject<T>() 
    { 
     return typeof(T) == typeof(object); 
    } 
Cuestiones relacionadas