Pregunta

No me refiero a la conversión dinámica en el sentido de convertir una interfaz inferior o una clase base a una clase más derivada, me refiero a tomar una definición de interfaz que he creado, y luego convertir dinámicamente a esa interfaz un objeto diferente NO derivado de esa interfaz pero soportando todas las llamadas.

Por ejemplo,

interface IMyInterface
{
   bool Visible
   {
      get;
   }
}

TextBox myTextBox = new TextBox();
IMyInterface i = (dynamic<IMyInterface>)myTextBox;

Esto podría lograrse en tiempo de compilación para tipos conocidos, y en tiempo de ejecución para instancias declaradas con dinámico. La definición de la interfaz es conocida, al igual que el tipo (en este ejemplo), por lo que el compilador puede determinar si el objeto es compatible con las llamadas definidas por la interfaz y realizar algo de magia para que tengamos la conversión.

Supongo que esto no se admite en C # 4 (no pude encontrar una referencia a él), pero me gustaría saberlo con seguridad. Y si no lo es, me gustaría discutir si debería incluirse en una futura variante del idioma o no, y las razones a favor y en contra. Para mí, me parece una buena adición para permitir un mayor polimorfismo en el código sin tener que crear tipos completamente nuevos para envolver los tipos de marco existentes.

Actualizar
Para que nadie me acuse de plagio, no tenía conocimiento de Jon Skeet ya había propuesto esto . Sin embargo, es bueno saber que pensamos en una sintaxis extremadamente similar, lo que sugiere que al menos podría ser intuitivo. Mientras tanto, " tienes una idea original " permanece en mi lista de deseos para otro día.

¿Fue útil?

Solución

Creo que Jon Skeet ha tenido una propuesta de este tipo ( http://msmvps.com/blogs/jon_skeet/archive/2008/10/30/c-4-0-dynamic-lt-t-gt.aspx ), pero hasta ahora, no he escuchado que C # 4.0 la tenga.

Otros consejos

Creo que eso es problemático. Está introduciendo el acoplamiento entre dos clases que no están acopladas.

Considere el siguiente código.

public interface IFoo
{
   int MethodA();
   int MethodB();
}

public class Bar
{
   int MethodA();
   int MethodB();
}

public class SomeClass
{
   int MethodFoo(IFoo someFoo);
}

¿Esto debería ser legal?

int blah = someClass.MethodFoo((dynamic<IFoo>)bar);

Parece que debería ser legal, porque el compilador debería poder escribir dinámicamente la barra como algo que implementa IFoo.

Sin embargo, en este punto está acoplando IFoo y Bar a través de una llamada en una parte completamente separada de su código.

Si editas Bar porque ya no necesita MethodB, de repente someClass.MethodFood ya no funciona, aunque Bar e IFoo no están relacionados.

De la misma manera, si agrega MethodC () a IFoo, su código se romperá de nuevo, aunque IFoo y Bar aparentemente no estén relacionados.

El hecho es que, aunque esto sería útil en casos selectos donde hay similitudes entre los objetos que no controla, hay una razón por la que las interfaces deben estar explícitamente vinculadas a los objetos, y la razón es para que el compilador pueda Garantizar que el objeto lo implemente.

No hay necesidad de que C # admita esto, ya que puede implementarse de forma muy limpia como biblioteca.

He visto tres o cuatro implementaciones separadas (comencé a escribir una yo mismo antes de encontrarlas). Aquí está el tratamiento más completo que he visto:

http://bartdesmet.net/blogs/bart/archive/2008/11/10/introducing-the-c-ducktaper-bridging-the-dynamic-world-with-the -static-world.aspx

Probablemente será aún más fácil de implementar una vez que el DLR esté integrado en el tiempo de ejecución.

Debido a que la clase de envoltorio / reenviador para una interfaz dada puede generarse una vez y luego almacenarse en caché, y luego un objeto dado de tipo desconocido puede envolverse una vez, hay mucho margen para el almacenamiento en caché de sitios de llamadas, etc. el rendimiento debe ser excelente.

En contraste, creo que la palabra clave dynamic , que es una característica del lenguaje y una enormemente compleja, es una digresión innecesaria y potencialmente desastrosa, convertida en un lenguaje que anteriormente tenía una Una clara filosofía de escritura estática, que le dio una dirección obvia para futuras mejoras. Deberían haberse apegado a eso y hacer que la inferencia de tipos funcionara mejor y mejor hasta que la escritura se volviera más invisible. Hay muchas áreas en las que podrían evolucionar el lenguaje, sin romper los programas existentes, y sin embargo no lo hacen, simplemente debido a las limitaciones de recursos (por ejemplo, la razón por la que var no se puede usar en más lugares) porque tendrían que volver a escribir el compilador y no tienen tiempo).

Todavía están haciendo cosas buenas en C # 4.0 (las características de la varianza) pero hay mucho más por hacer para hacer que el sistema de tipos sea más inteligente, más automático y más poderoso para detectar problemas en el momento de la compilación. En su lugar, esencialmente estamos recibiendo un truco.

El marco de código abierto Impromptu-Interface hace esto usando C # 4 y el dlr .

using ImpromptuInterface;

interface IMyInterface
{
   bool Visible
   {
      get;
   }
}

TextBox myTextBox = new TextBox();
IMyInterface i = myTextBox.ActLike<IMyInterface>();

Ya que usa el dlr, también funcionará con ExpandoObject y DynamicObject.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top