Question

Tout en inspectant les délégués en C # et .NET en général, j'ai remarqué quelques faits intéressants:

La création d'un délégué en C # crée une classe dérivée de MulticastDelegate avec un constructeur:

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

Ce qui signifie qu'il attend l'instance et un pointeur vers la méthode. Pourtant, la syntaxe de la construction d'un délégué en C # suggère qu'il a un constructeur

new MyDelegate(int () target)

où je peux reconnaître int () comme instance de fonction (int *target() serait un pointeur de fonction dans C ++). Donc, évidemment, le compilateur C # choisit la méthode correcte du groupe de méthode défini par le nom de la fonction et construit le délégué. Donc, la première question serait, d'où le compilateur C # (ou Visual Studio, est-il précis) choisit-il cette signature de constructeur? Je n'ai remarqué aucun attribut spécial ou quelque chose qui ferait une distinction. Est-ce une sorte de compilateur / VisualStudio Magic? Sinon, c'est le T (args) target construction valide en C #? Je n'ai pas réussi à obtenir quoi que ce soit à compiler, par exemple:

int () cible = myMethod;

est invalide, donc faire n'importe quoi avec MyMetod, par exemple l'appel .ToString() là-dessus (enfin cela a un certain sens, car c'est techniquement une méthode groupe, mais j'imagine qu'il devrait être possible de choisir explicitement une méthode en casting, par exemple (int())MyFunction. Alors, toute cette magie purement du compilateur? En regardant la construction à travers le réflecteur révèle une autre syntaxe:

Func CS 1 $ 0000 $ = new func (null, (intptr) foo);

Cela est cohérent avec la signature du constructeur démonté, mais cela ne se compile pas!

Une dernière note intéressante est que les classes Delegate et MulticastDelegate ont encore d'autres ensembles de constructeurs:

.Method Family HideBySig SpecialName RTSpecialName Instance void .CTOR (Class System.Type Target, String 'Method') CIL Managed

Où est la transition d'un pointeur d'instance et de méthode vers un type et un nom de méthode de chaîne se produit-il? Cela peut-il être expliqué par le runtime managed Mots-clés dans la signature du constructeur du délégué personnalisé, c'est-à-dire que le temps d'exécution fait-il son travail ici?

ÉDITER: OK, donc je suppose que je devrais reformuler ce que je voulais dire par cette question. En gros Visual Studio La magie, puisque Intellisense expose une nouvelle syntaxe lorsque vous suggérez les arguments du constructeur et en cache même l'un d'eux (par exemple, le réflecteur n'utilise pas cette syntaxe et cette concurrents, d'ailleurs).

Je me demandais si cette affirmation est vraie, et si la syntaxe de l'instance de fonction a une signification plus profonde en C # ou est-ce juste un format constant implémenté par la partie magique Visual Studio pour plus de clarté (ce qui a du sens, car il ressemble à C # non valide)? En bref, si je mets en œuvre Intellisense, devrais-je faire de la magie pour les délégués ou pourrais-je construire la suggestion par un mécanisme intelligent?

Modifier final: Ainsi, le consensus populaire est que c'est vraiment vs magie. Voir d'autres exemples (voir le commentaire de Marc Gravell) d'un tel comportement me convainc que c'est le cas.

Était-ce utile?

La solution

Le premier argument est résolu à partir de la référence d'objet (ou null pour les méthodes statiques); pas de magie là-bas.

Êtes le deuxième L'argument, cependant - il s'agit d'un pointeur non géré (natif int); Bref, il n'y a pas d'alternative direct Syntaxe C # qui peut utiliser ce constructeur - il utilise une instruction IL spécifique (ldftn) pour résoudre la fonction des métadonnées. Cependant, vous pouvez utiliser Delegate.CreateDelegate Pour créer des délégués via la réflexion. Vous pouvez également utiliser il émettre (DynamicMethod etc), mais ce n'est pas amusant.

Autres conseils

Vous définissez d'abord le délégué (c'est ainsi que Visual Studio connaît la signature de la méthode cible):

delegate void MyDelegate();

Ensuite, vous construisez des instances de délégués comme ceci:

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 # choisit automatiquement la méthode correspondant à la signature du délégué.

Edit: lorsque l'intelligence de Visual Studio vous montre le int () target Suggestion, cela vous montre la signature des méthodes C # que vous pouvez utiliser. Le compilateur C # traduit la représentation C # en IL. L'implémentation IL sera différente, car IL n'est pas un langage de style C, et le compilateur C # fournit du sucre syntaxique pour abstraire les détails de la mise en œuvre.

C'est juste une supposition, alors ne me tirez pas dessus si je me trompe, mais je pense que Intellisense obtient la signature de la méthode cible de la Invoke Méthode définie sur le délégué. Le réflecteur montre clairement que le Invoke méthode sur System.Action<T> est:

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

Qui est la même que la suggestion de signature offerte par Intellisense. La magie est Intellisense, lorsque vous repérez un type de délégué, regarde le Invoke Méthode et suggère un constructeur qui prend une cible qui correspond.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top