Les délégués avec la valeur de retour l'inférence de type (C#)
Je suis encore nouveau pour les délégués et j'ai été jouer avec la fonction de Délégué Couche d'Accès aux Données décrites dans Steven John Metsker "Patrons de Conception en C#" livre (excellent!). Il définit les données d'accès délégué comme ceci:
public delegate object BorrowReader(IDataReader reader);
Le résultat de l'utilisation de ce code qui ressemble à l'un de ces:
var result = Foo.Bar(new BorrowReader(DoFooBarMagic));
var result = Foo.Bar(DoFooBarMagic);
Cependant, depuis le délégué du type de retour est "objet", vous devez effectuer un cast pour obtenir quelle que soit la méthode ("DoFooBarMagic" dans cet exemple) retourne vraiment. Donc, si "DoFooBarMagic" retourne la Liste, vous devez faire quelque chose comme ceci:
var result = Foo.Bar(DoFooBarMagic) as List<string>;
Ce que j'aimerais c'est être capable de sauter le casting et avoir le type de retour de la délégué déduit du type de retour de la méthode du délégué. Je pensais peut-être il y a un moyen d'utiliser un paramètre de Type d'inférence du type de retour. Quelque chose comme un de ces:
public delegate T BorrowReader<T>(IDataReader reader);
List<string> result = Foo.Bar(new BorrowReader(DoFooBarMagic));
//Look, Ma, no cast!
var result2 = Foo.Bar(DoFooBarMagic);
Où le type de retour est déduit à partir du type de retour de la méthode du délégué, mais qui s'avère ne pas fonctionner. Au lieu de cela vous avez à faire cela:
public delegate T BorrowReader<T>(IDataReader reader);
var result = Foo.Bar(new BorrowReader<List<string>>(DoFooBarMagic));
Qui ne semble guère mieux que la fonte.
Donc, il y a un moyen de déduire le type de retour de la déléguée du type de retour de la méthode du délégué?
Modifier pour Ajouter:
Je peux changer la signature de Foo.Bar en cas de besoin. La signature actuelle est essentiellement ceci:
public static T Bar<T>(string sprocName,
DbParameter[] params,
BorrowReader<T> borrower);
Remarque: cette signature est le résultat de l'état actuel, qui est à l'aide de ce délégué définition:
public delegate T BorrowReader<T>(IDataReader reader);
OriginalL'auteur Josh | 2009-05-12
Vous devez vous connecter pour publier un commentaire.
Comment sur:
Je sais qu'il est encore en train de faire le casting de toute façon, ce qui est laid, mais il devrait fonctionner. (J'ai d'abord pensé que vous pourriez sortir avec une conversion implicite de
func
, mais apparemment pas. Au moins pas avant C# 4.0.)Bien sûr, si vous pouvez changer la signature de
Foo.Bar
pour être générique, vous riez...EDIT: Pour répondre aux commentaires: si la signature de la méthode est modifié pour prendre un délégué générique, par exemple
puis le code appelant peut près de simplement être:
Malheureusement, l'inférence de type qui ne fonctionne pas avec la méthode des groupes, donc vous devez utiliser soit:
ou (plus agréable, si légèrement moins efficace)
De sorte que vous êtes en droit - cette réponse n'a pas tout à fait obtenir l'OP exactement ce qui était nécessaire, mais sans doute assez proche pour obtenir l'acceptation. Nous espérons que cette édition est utile pour expliquer le reste 🙂
Si cela va être de parler à une base de données dans la vraie vie, alors les performances de la distribution va être insignifiant.
Très vrai. Mais cela ne signifie pas que nous n'essayons pas parfait! 🙂
J'ai raté la dernière déclaration. Je peux changer de Foo.Bar. Je vais éditer pour ajouter la signature.
Pour ceux d'entre nous qui sont lentes, on peut voir comment l'appel sera de travailler avec cette réponse? Je vais avoir de la difficulté à voir comment cette aide.
OriginalL'auteur Jon Skeet
C'est moche, mais vous pouvez utiliser un paramètre de sortie. De mon enum analyseur:
La seconde va déduire le type, mais comme je l'ai dit, c'est moche.
En terme de Performance, je n'ai pas vu une différence. Lisibilité-sage, il a vraiment aidé dans la 2.0 quand j'avais Map/reduce de fonctions dont les génériques et complet de noms de type. De 300 lignes de caractères sont une vraie douleur à lire, même si vous les briser en lignes distinctes, et cela me fit la même chose sur une ligne sans avoir à utiliser les deux écrans.
OriginalL'auteur Chris Doggett
Je ne pense pas qu'il y a un moyen de contourner cela. Au moins pas de la façon dont vous le proposer. Le principal problème étant que depuis il a à inférer au moment de la compilation, si vous n'avez pas explicitement le type de retour, alors le compilateur ne peut pas déduire le type de retour.
OriginalL'auteur enriquein
Pas l'utilisation de génériques. L'inférence de Type est un moment de la compilation de l'événement. Une solution serait d'avoir un délégué générique que vous avez posté. Le délégué générique serait plus rapide qu'un cast.
Comme je l'ai dit, l'inférence de type est faite par le compilateur, le casting se passe au moment de l'exécution.
OriginalL'auteur JohnOpincar
Il ne vous donne pas ce que veulent les "Foo.Bar(DoFooBarMagic)". J'ai surtout ajouté qu'il est complet, puisque personne n'avait proposé qu'elle encore. C'est plus consice que "Foo.Bar(nouveau BorrowReader<..>(..))" et il est aussi bon que vous pouvez obtenir sans avoir recours à la coulée.
OriginalL'auteur Lucas
J'attends F# peut le faire. Je ne suis pas expert, mais F# n'utilisez le type de retour de l'inférence de type (détails sur MSDN).
OriginalL'auteur Alex