Domanda

Durante l'ispezione dei delegati in C# e .NET in generale, ho notato alcuni fatti interessanti:

La creazione di un delegato in C# crea una classe derivata da MulticastDelegate con un costruttore:

.method public hidebysig specialname rtspecialname instance 
   void .ctor(object 'object', native int 'method') runtime managed { }

Ciò significa che si aspetta l'istanza e un puntatore al metodo.Tuttavia, la sintassi della costruzione di un delegato in C# suggerisce che disponga di un costruttore

new MyDelegate(int () target)

dove posso riconoscere int () come istanza di funzione (int *target() sarebbe un puntatore a funzione in C++).Quindi ovviamente il compilatore C# seleziona il metodo corretto dal gruppo di metodi definito dal nome della funzione e costruisce il delegato.Quindi la prima domanda sarebbe: da dove prende il compilatore C# (o Visual Studio, per la precisione) questa firma del costruttore?Non ho notato alcun attributo speciale o qualcosa che potesse fare una distinzione.È una sorta di magia del compilatore/visualstudio?In caso contrario, è il T (args) target costruzione valida in C#?Non sono riuscito a ottenere nulla da compilare, ad esempio:

int() destinazione = MioMetodo;

non è valido, così come qualsiasi cosa con MyMetod, per esempio.chiamando .ToString() su di esso (beh, questo ha un senso, dato che tecnicamente è un metodo gruppo, ma immagino che dovrebbe essere possibile scegliere esplicitamente un metodo tramite casting, ad es. (int())MyFunction.Quindi tutta questa è magia puramente del compilatore?Osservando la costruzione attraverso un riflettore si rivela ancora un'altra sintassi:

Funz CS$1$0000 = nuova Funz(null, (IntPtr) Foo);

Ciò è coerente con la firma del costruttore disassemblato, ma non viene compilato!

Un'ultima nota interessante è che le classi Delegate E MulticastDelegate hanno ancora un altro set di costruttori:

.Method Famiglia HideBysig SpecialName RtspecialName istanza void .Ctor (classe System.Type Target, String 'Method') Cil gestito

Dove avviene la transizione da un'istanza e un puntatore al metodo a un tipo e al nome di un metodo stringa?Ciò può essere spiegato dal runtime managed parole chiave nella firma del costruttore del delegato personalizzato, ad es.il runtime fa il suo lavoro qui?

MODIFICARE:ok, quindi immagino che dovrei riformulare ciò che volevo dire con questa domanda.Fondamentalmente sto suggerendo che non c'è solo la magia del compilatore C#/CLR coinvolta nella costruzione del delegato, ma anche alcuni Studio visivo magia, dal momento che Intellisense lancia qualche nuova sintassi quando suggerisce gli argomenti del costruttore e ne nasconde persino uno (ad es.Reflector non utilizza questa sintassi e questo costruttore, del resto).

Mi chiedevo se questa affermazione è vera e se la sintassi dell'istanza della funzione ha un significato più profondo in C# o è solo un formato costante implementato dalla parte magica di Visual Studio per chiarezza (il che ha senso, poiché sembra C# non valido)?In breve, se implementassi Intellisense, dovrei fare qualche magia per i delegati o potrei costruire il suggerimento con qualche meccanismo intelligente?

MODIFICA FINALE:quindi, il consenso popolare è che questa è davvero magia VS.Vedere altri esempi (vedi il commento di Marc Gravell) di tale comportamento VS mi convince che sia così.

È stato utile?

Soluzione

Il primo argomento viene risolto dal riferimento all'oggetto (o null per metodi statici);nessuna magia lì.

Riguardo il secondo argomento, tuttavia: è un puntatore non gestito (int nativo);insomma, non c’è alternativa diretto Sintassi C# che può utilizzare questo costruttore: utilizza un'istruzione IL specifica (ldftn) per risolvere la funzione dai metadati.Tuttavia, puoi usare Delegate.CreateDelegate creare delegati attraverso la riflessione.Puoi anche usare IL emit (DynamicMethod ecc.), ma non è divertente.

Altri suggerimenti

Per prima cosa definire il delegato (questo è il modo di Visual Studio conosce la firma del metodo di destinazione):

delegate void MyDelegate();

Poi si costruisce le istanze delegato in questo modo:

MyDelegate method = new MyDelegate({method name});

// If this was the method you wanted to invoke:
void MethodToInvoke()
{
    // do something
}

MyDelegate method = new MyDelegate(MethodToInvoke);

C # preleva automaticamente il metodo di corrispondenza della firma del delegato.

Modifica: Quando Intellisense di Visual Studio vi mostra il suggerimento int () target, sta mostrando la firma del C # i metodi che è possibile utilizzare. Il compilatore C # traduce la # rappresentazione C a IL. L'implementazione IL avrà un aspetto diverso, perché IL non è un linguaggio di stile C, e il compilatore C # fornisce zucchero sintattico per astrarre i dettagli di implementazione.

Questa è solo una supposizione, quindi non mi spara se sbaglio, ma credo che Intellisense è sempre la firma per il metodo di destinazione dal metodo Invoke definito sul delegato. Riflettore mostra chiaramente che il metodo Invoke su System.Action<T> è:

[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)]
public virtual void Invoke(T obj);

Che è la stessa della suggestione firma offerto da Intellisense. La magia è Intellisense, quando avvistare un tipo delegato, guarda il metodo Invoke e suggerisce un costruttore che prende un target che corrisponde esso.

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