Implementazione di un tipo di anatra sicuro in C#
-
20-09-2019 - |
Domanda
Dopo aver visto come andare Gestisce le interfacce e mi piace, ho iniziato a pensare a come potresti ottenere un simile tipo di anatra in C# in questo modo:
var mallard = new Mallard(); // doesn't implement IDuck but has the right methods
IDuck duck = DuckTyper.Adapt<Mallard,IDuck>(mallard);
Il DuckTyper.Adapt
Il metodo userebbe System.Reflection.Emit
per costruire un adattatore al volo. Forse qualcuno ha già scritto qualcosa del genere. Immagino che non sia troppo diverso da quello che fanno già i framework deriduali.
Tuttavia, ciò lancerebbe eccezioni in fase di esecuzione se Mallard
In realtà non ha il diritto IDuck
metodi. Per ottenere l'errore prima al momento della compilazione, dovrei scrivere a MallardToDuckAdapter
Questo è esattamente quello che sto cercando di evitare.
C'è un modo migliore?
modificare: Apparentemente il termine corretto per quello che chiamo "tipo di anatra" è digitazione strutturale.
Soluzione
Come puoi sapere se una mucca cammina come un'anatra e ciarlatani come un'anatra se non hai una mucca da vivere e respirare davanti a te?
Il tipo di anatra è un concetto usato in fase di esecuzione. Un concetto simile al tempo di compilazione è digitazione strutturale che è afaik non supportato dal CLR. (Il CLR è incentrato su digitazione nominativa.)
Un sistema di tipo strutturale] contrasta con i sistemi nominativi, in cui i confronti si basano su dichiarazioni esplicite o sui nomi dei tipi e la tipizzazione delle anatre, in cui è verificata la compatibilità solo la parte della struttura in fase di esecuzione.
Il solito modo per garantire che il tipo di anatra non lancia alcuna eccezione in fase di esecuzione sono test unitari.
Altri suggerimenti
Riflesso.emit viene utilizzato per emettere il che chiama direttamente l'oggetto originale
Non credo che questa biblioteca ti darà degli errori del tempo di compilazione pensato, non sono sicuro che sarebbe del tutto fattibile. Utilizzare i test unitari per aiutare a compensare questo.
Non credo che ci sia un altro modo in cui otterresti un errore di tempo di compilazione.
Tuttavia, questo è qualcosa per cui il test unitario è ottimo. Scriveresti un test unitario per verificarlo
DuckTyper.Adapt<Mallard, IDuck>(mallard);
mappe con successo.
So che le interfacce implicite (che sono le interfacce Go sono) sono state pianificate per VB 10 (non ho idea di C#). Sfortunatamente, sono stati demoliti prima del rilascio (penso che non siano nemmeno entrati in beta ...). Sarebbe bello vedere se faranno l'apparizione in una versione futura di .NET.
Certo, il nuovo dynamic
I tipi possono essere usati per ottenere più o meno lo stesso, ma questo non è ancora lo stesso: le interfacce implicite consentono ancora una forte digitazione, che trovo importante.