8
votes

"Sans heurt" une méthode d'instance dans .NET

Pouvez-vous créer un délégué d'une méthode d'instance sans spécifier l'instance au moment de la création? En d'autres termes, pouvez-vous créer un délégué "statique" qui prend telle première paramètre l'instance que la méthode doit être appelée?

Par exemple, comment construire le délégué suivant à l'aide de la réflexion? P>

var func37 = (Func<CultureInfo,string>)(37.ToString);
var toStringMethod = typeof(int).GetMethod("ToString", BindingFlags.Instance | BindingFlags.Public, null, new Type[] {typeof(CultureInfo) }, null);
var func42 = (Func<CultureInfo,string>)Delegate.CreateDelegate(typeof(Func<CultureInfo,string>), 42, toStringMethod,true);
Console.WriteLine( object.ReferenceEquals(func37.Method,func42.Method)); //true
Console.WriteLine(func37.Target);//37
Console.WriteLine(func42.Target);//42
Console.WriteLine(func37(CultureInfo.InvariantCulture));//37
Console.WriteLine(func42(CultureInfo.InvariantCulture));//-201040128... WTF?


0 commentaires

4 Réponses :


3
votes

Je ne suis pas sûr, mais peut être Ouvrir les délégués peut vous aider.

upd upd: suivez ce lien , Si le premier ne fonctionne pas.


3 commentaires

Ce lien mène à une 404 page - vous êtes peut-être mis en erreur?


Weird, en cliquant sur le lien qui m'amène à une page 404, rafraîchissant la page provoque le même 404 - mais appuyez sur Entrée dans la barre d'URL (c'est-à-dire supprimer le référateur) apporte la page. Certains bugs de navigateur / serveur, apparemment (FF3.5.1 uniquement - chrome fonctionne bien). De toute façon, j'ai trouvé la page maintenant ;-)


Merci, Eamon. C'est la première fois que je vois ce bogue, généralement des liens de blogueurs fonctionnent bien.



0
votes

La voie du goog peut peut-être utiliser le type "dynamique" dans .NET 4.0. Cependant, le délégué a besoin de l'instance (pour des méthodes non statiques). Les problèmes sont plus complexes puis des loks à la première fois à cause de polymorfisme, etc.


0 commentaires

12
votes

Vous avez effectivement choisi un exemple particulièrement délicat, pour deux raisons:

  • Tostring () est une méthode virtuelle héritée de objet mais remplacé dans int32 . .
  • int est un type de valeur et il y a des règles étranges avec délégué.createdélégate () En ce qui concerne les types de valeur et les méthodes d'instance - le premier paramètre effectif devient essentiellement ref int plutôt que int

    Cependant, voici un exemple de string.toupper , qui n'a pas non plus de ces problèmes: xxx

    si C'est assez bon pour vous, super ... si vous voulez vraiment int.tostring , je vais devoir essayer un peu plus difficile :)

    Voici un exemple de type de valeur , en utilisant un nouveau type de délégué qui prend son premier paramètre par référence: xxx


13 commentaires

C'est l'un de ces cas où il devient clair que c # a encore de la place pour devenir une langue fonctionnelle. Traiter les fonctions de citoyens de première classe n'est toujours pas aussi transparente que nous le souhaitons. Y a-t-il un moyen d'exploiter les fonctionnalités dynamiques du C # 4 pour rendre ce genre de chose plus facile?


@Lbushkin: Je ne pense pas. En fait, la typage dynamique et les lambdas ne vont pas terriblement bien ensemble pour commencer avec - le compilateur doit savoir quel type pour convertir l'expression de Lambda à la compilation.


Je avait Tests sur Int.Tostring, mais pour une utilisation réelle, je suppose que je pouvais faire sans méthodes virtuelles - bien que non sans structs. De toute façon, merci pour la tête, j'avais négligé la complexité des méthodes virtuelles et le message d'erreur n'est pas exactement informatif ...


Wow, tu es rapide ;-). Je ne suis pas sûr que ce soit possible - j'ai essayé de regarder à travers MethodInfo.invoke avec le réflecteur pour voir si elle traite des structs spécialement, mais cela finit par un code natif (certains talons CLR, sans aucun doute).


On dirait que INT est un cas particulier? Le code semblable à votre ne fonctionne pas pour un int. Bizarre. Ce n'est pas qu'il soit impossible de faire des solutions de contournement pour des types de construction, mais c'est étrange.


@Amon: Quelle méthode essayiez-vous d'utiliser? Il faudrait être une méthode d'instance non virtuelle, je soupçonne. Tout est un peu complexe ...


Y a-t-il une page où votre deuxième point de balle ("règles étranges") est documentée? Je ne trouve aucun endroit où le fait que le premier paramètre devienne transmis par référence sauf cette réponse.


@Lazlo: Je ne suis pas sûr - je ne me souviens pas de détails moi-même, j'ai peur.


10 ans plus tard ... je suppose que la langue manque toujours dans cette zone? J'ai besoin de lier la déléguée à la propriété Getter pour le type de structure inconnu à l'heure de la compilation. :( est-ce même possible?


@Jameshoux: C'est possible que certaines des modifications ref C # 7 aideraient, mais je ne suis pas sûr. Il serait peut-être préférable de poser une nouvelle question avec votre exemple spécifique et de ce que vous avez essayé.


@ Jonskeet en fait ... On dirait que j'étais complètement confus. Je pensais que votre suggestion de "Reffunc <>" était strictement hypothétique. Vous étiez, en fait en disant que Reffunc est réel! J'ai essayé Reffunc <> et compiler me dit son type inconnu! Ctrl +. ne montre aucune solution. Comment puis-je utiliser Reffunc <>?


@Jameshoux: C'est un type de délégué déclaré dans la catégorie test .


@Jonskeet oh mon. J'ai complètement manqué ça. Je pense que je développe une cécité de code ou quelque chose. Lol merci pour la réponse!



2
votes

Vous pouvez utiliser des lambdas pour obtenir un wrapper statique "un peu" compilé pour votre méthode d'instance.

L'échantillon ci-dessous n'est pas vraiment rapide, mais il devrait être nettement plus rapide que toute invocation dynamique simple.

la sortie xxx

le code xxx


0 commentaires