Domanda

Non intendo il casting dinamico nel senso di trasmettere un'interfaccia o una classe base inferiore a una classe più derivata, intendo prendere una definizione di interfaccia che ho creato e quindi lanciare dinamicamente su quell'interfaccia un oggetto diverso NOT derivato da tale interfaccia ma supportando tutte le chiamate.

Ad esempio,

interface IMyInterface
{
   bool Visible
   {
      get;
   }
}

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

Ciò potrebbe essere ottenuto in fase di compilazione per tipi noti e runtime per istanze dichiarate con dinamico. La definizione dell'interfaccia è nota, così come il tipo (in questo esempio), quindi il compilatore può determinare se l'oggetto supporta le chiamate definite dall'interfaccia ed eseguire un po 'di magia per noi per avere il cast.

La mia ipotesi è che questo non è supportato in C # 4 (non sono riuscito a trovare un riferimento ad esso), ma mi piacerebbe saperlo con certezza. E se non lo è, vorrei discutere se dovrebbe essere incluso in una futura variante della lingua o meno, e le ragioni a favore e contro. A me sembra una buona aggiunta consentire un maggiore polimorfismo nel codice senza dover creare tipi completamente nuovi per avvolgere i tipi di framework esistenti.

Aggiorna
Per timore che qualcuno mi accusasse di plagio, non ero a conoscenza di Jon Skeet lo ha già proposto . Tuttavia, è bello sapere che abbiamo pensato a una sintassi estremamente simile, il che suggerisce che potrebbe essere almeno intuitivo. Nel frattempo, "hai un'idea originale" rimane nella mia lista dei desideri per un altro giorno.

È stato utile?

Soluzione

Penso che Jon Skeet abbia avuto una proposta simile ( http://msmvps.com/blogs/jon_skeet/archive/2008/10/30/c-4-0-dynamic-lt-t-gt.aspx ), ma finora non ho sentito che C # 4.0 lo avrà.

Altri suggerimenti

Penso che sia problematico. Stai introducendo l'accoppiamento tra due classi che non sono accoppiate.

Considera il seguente codice.

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

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

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

dovrebbe essere legale?

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

Sembra come dovrebbe essere legale, perché il compilatore dovrebbe essere in grado di digitare dinamicamente la barra come qualcosa che implementa IFoo.

Tuttavia, a questo punto stai accoppiando IFoo e Bar attraverso una chiamata in una parte completamente separata del tuo codice.

Se modifichi la barra perché non ha più bisogno del metodo B, improvvisamente someClass.MethodFood non funziona più, anche se Bar e IFoo non sono correlati.

Allo stesso modo, se aggiungi MethodC () a IFoo, il tuo codice si spezzerebbe di nuovo, anche se apparentemente IFoo e Bar non sono correlati.

Il fatto è che, sebbene ciò sia utile in determinati casi in cui vi sono somiglianze tra oggetti che non si controllano, c'è una ragione per cui le interfacce devono essere esplicitamente collegate agli oggetti, e la ragione è che il compilatore può garantire che l'oggetto lo implementi.

Non è necessario che C # lo supporti, poiché può essere implementato in modo molto pulito come libreria.

Ho visto tre o quattro implementazioni separate (ho iniziato a scriverne una da solo prima di trovarle). Ecco il trattamento più completo che abbia mai visto:

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

Probabilmente sarà ancora più facile da implementare una volta che il DLR è integrato nel runtime.

Poiché la classe wrapper / forwarder per una determinata interfaccia può essere generata una volta e poi memorizzata nella cache, e quindi un determinato oggetto di tipo sconosciuto può essere impacchettato una volta, c'è un sacco di spazio per la memorizzazione nella cache dei siti di chiamata, ecc. le prestazioni dovrebbero essere eccellenti.

Al contrario, penso che la parola chiave dynamic , che è una caratteristica del linguaggio, e estremamente complessa, sia una digressione inutile e potenzialmente disastrosa, calpestata da un linguaggio che in precedenza aveva chiara filosofia di scrittura statica, che gli ha dato una direzione ovvia per miglioramenti futuri. Avrebbero dovuto attenersi a ciò e far sì che l'inferenza del tipo funzionasse sempre meglio fino a quando la digitazione diventasse più invisibile. Ci sono così tante aree in cui potrebbero evolvere la lingua, senza rompere i programmi esistenti, eppure non lo fanno, semplicemente a causa di vincoli di risorse (ad esempio il motivo per cui var non può essere utilizzato in più luoghi è perché dovrebbero riscrivere il compilatore e non hanno tempo).

Stanno ancora facendo buone cose in C # 4.0 (le caratteristiche della varianza) ma c'è così tanto altro che potrebbe essere fatto per rendere il sistema più intelligente, più automatico, più potente nel rilevare i problemi in fase di compilazione. Invece, stiamo essenzialmente ottenendo un trucco.

Il framework opensource Impromptu-Interface fa questo usando C # 4 e il dlr .

using ImpromptuInterface;

interface IMyInterface
{
   bool Visible
   {
      get;
   }
}

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

Poiché utilizza dlr, funzionerà anche con ExpandoObject e DynamicObject.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top