2012-03-23 11 views
17

Según tengo entendido, cada idioma puede tener su propio controlador dynamic, de modo que se apliquen las reglas apropiadas. No estoy seguro si lo siguiente es correcto/incorrecto; pensamientos?¿Debería invocar un método basado en la interfaz que utiliza "dinámico" obedecer las reglas de resolución del método C#?

Escenario: dos interfaces (uno implementa la otra) con algunos métodos:

public interface IA { 
    void Bar(object o); 
} 
public interface IB : IA { 
    void Foo(object o); 
} 

y una implementación básica:

public class B : IB { 
    public void Foo(object o) { Console.WriteLine("Foo"); } 
    public void Bar(object o) { Console.WriteLine("Bar"); } 
} 

Ahora, con # C normales (sin dynamic), podemos acceder métodos de IA de un objetivo de tipo IB:

IB b = new B(); 
var o = new { y = "z" }; 
b.Foo(o.y); // fine 
b.Bar(o.y); // fine 

Ahora vamos a añadir deliberadamente algunos dynamic a los argumentos, lo que hace que el procesamiento de toda utilización de invocación dynamic (como en el caso general esta resolución podría afectar a la sobrecarga, aunque no lo hará aquí):

IB b = new B(); 
dynamic x = new {y = "z"}; 
b.Foo(x.y); // fine 
b.Bar(x.y); // BOOM! 

que falle con el RuntimeBinderException:

'IB' no contiene una definición para 'Bar'

Ahora, lo que dice i s completamente correcto en tanto como IBno tiene un método Bar. Sin embargo, como se ilustra en el primer ejemplo: bajo las reglas normales de C# se esperaría que dado que el tipo de declaración del objetivo es una interfaz (IB), las otras interfaces conocidas para implementarse (es decir, IA) se verifican como parte de la resolución de sobrecarga.

Entonces, ¿esto es un error? ¿O estoy malinterpretando?

+0

+1 Interesante. Me pregunto si el DLR ofrece menos soporte para este tipo de cosas en comparación con el compilador/CLR. Supongo que el DLR es responsable del intento de resolución de la llamada. –

+0

@ Adam, mi entendimiento es que para las llamadas basadas en la reflexión, hay un proveedor específico del idioma, precisamente para seguir las convenciones del lenguaje, es decir, 'Microsoft.CSharp.RuntimeBinder.Binder' –

+0

¿Observas lo mismo con la herencia de clases tratando de llamar métodos de base? (A diferencia de los métodos de interfaz heredados). –

Respuesta

6

Esta es una limitación bien conocida de la carpeta, se le preguntó varias veces en SO y el tema de this feedback article. Voy a citar la respuesta de Microsoft:

Esta fue un área que explicitamos explícitamente debido al tiempo en el envío de C# 4.0 y nos encantaría volver a visitar esto. Este caso específico de los métodos ISet/IList que en realidad se definen en ICollection es el lugar más visible donde no excavar a través de las interfaces padre limita innecesariamente el alcance del enlace dinámico en C#.

Esperamos agregar pronto este soporte, aunque este problema actualmente se encuentra justo debajo de nuestra línea de corte de triage de errores. Estamos marcando el problema No se corrige para indicar que actualmente no estamos realizando un seguimiento para solucionar este problema en la próxima versión de Visual Studio. Reactivaremos esta falla durante el próximo año si llegamos más allá de lo esperado a través de nuestra lista de triage de errores, o si volvemos a visitar el error para la siguiente versión.

Lo que no sucedió aún, afaik. El artículo no tiene muchos votos.

Cuestiones relacionadas