Implementando la tipificación segura de patos en C#
adapter duck-typing (4)
¿Cómo puedes saber si una vaca camina como un pato y graciosa como un pato si no tienes una vaca viva y respirando frente a ti?
Duck-typing es un concepto utilizado en tiempo de ejecución. Un concepto similar en tiempo de compilación es la tipificación estructural que AFAIK no es compatible con el CLR. (El CLR se centra alrededor de la tipificación nominal ).
[Un sistema de tipo estructural] contrasta con los sistemas nominativos, donde las comparaciones se basan en declaraciones explícitas o los nombres de los tipos y en la tipificación de pato, en la que solo se verifica la compatibilidad de la parte de la estructura a la que se accede en el tiempo de ejecución.
La forma habitual de garantizar que los lanzamientos de escritura de pato no sean una excepción en el tiempo de ejecución son las pruebas unitarias.
Después de ver cómo Go maneja las interfaces y me gusta, comencé a pensar en cómo podrías lograr una escritura similar en C # de esta manera:
var mallard = new Mallard(); // doesn''t implement IDuck but has the right methods
IDuck duck = DuckTyper.Adapt<Mallard,IDuck>(mallard);
El método DuckTyper.Adapt
usaría System.Reflection.Emit
para construir un adaptador sobre la marcha. Tal vez alguien ya ha escrito algo como esto. Supongo que no es muy diferente de lo que ya hacen los marcos burlones.
Sin embargo, esto generaría excepciones en tiempo de ejecución si Mallard
no tiene los métodos IDuck
correctos. Para obtener el error antes en el momento de la compilación, tendría que escribir un MallardToDuckAdapter
que es exactamente lo que estoy tratando de evitar.
¿Hay alguna manera mejor?
edición : aparentemente, el término apropiado para lo que yo llamo "tipificación segura de pato" es tipificación estructural .
No creo que haya otra forma en la que obtendrías un error de compilación.
Sin embargo, esto es algo para lo que Unit Unit es ideal. Escribirías una prueba unitaria para verificar que
DuckTyper.Adapt<Mallard, IDuck>(mallard);
mapas con éxito.
Sé que las interfaces implícitas (que son las interfaces de Go) fueron planeadas para VB 10 (no tengo idea acerca de C #). Desafortunadamente, fueron desechados antes de su lanzamiento (creo que ni siquiera llegaron a la versión beta ...). Sería bueno ver si aparecerán en una versión futura de .NET.
Por supuesto, los nuevos tipos dynamic
se pueden usar para lograr lo mismo pero esto no es lo mismo: las interfaces implícitas aún permiten una tipificación fuerte, lo que me parece importante.
Reflection.Emit se usa para emitir IL que llama directamente al objeto original
No creo que esta biblioteca te dé errores de compilación, no estoy seguro de que sea completamente factible. Use Pruebas Unitarias para ayudar a compensar eso.