Func <T> sans paramètre out


167

Puis-je passer une méthode avec un paramètre out comme Func?

public IList<Foo> FindForBar(string bar, out int count) { }

// somewhere else
public IList<T> Find(Func<string, int, List<T>> listFunction) { }

Func a besoin d'un type pour que out n'y soit pas compilé, et l'appel de listFunction nécessite un int et n'autorisera pas un out in.

Y a-t-il un moyen de faire cela?

Réponses:


228

refet outne font pas partie de la définition du paramètre de type de sorte que vous ne pouvez pas utiliser le intégré Funcdélégué pour passer refet outarguments. Bien sûr, vous pouvez déclarer votre propre délégué si vous le souhaitez:

delegate V MyDelegate<T,U,V>(T input, out U output);

7
Dans C # 4 (2010) et versions ultérieures (n'a pas été publié lorsque vous avez écrit votre réponse), il est possible de marquer Tcomme contravariant et Vcomme covariant. Cependant, comme un paramètre ( output) de type Uest passé par référence , Uil ne peut pas être marqué co- ou contravariant et doit rester "invariant". Considérez donc public delegate V MyDelegate<in T, U, out V>(T input, out U output);si vous utilisez C # 4 ou une version ultérieure.
Jeppe Stig Nielsen


24

Pourquoi ne pas créer une classe pour encapsuler les résultats?

public class Result
{
     public IList<Foo> List { get; set; }
     public Int32 Count { get; set; }
}

13

La Funcfamille de délégués (ou Actiond'ailleurs) n'est rien d'autre que de simples types de délégués déclarés comme

//.NET 4 and above
public delegate TResult Func<out TResult>()
public delegate TResult Func<in T, out TResult>(T obj)

//.NET 3.5
public delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
public delegate TResult Func<T1, T2, T3, TResult>(T1 obj1, T2 obj2, T3 obj3)

etc. Les délégués en tant que tels peuvent avoir des paramètres out / ref, donc dans votre cas ce n'est qu'une question d'implémentation personnalisée par vous-même comme d'autres réponses l'ont souligné. Quant à savoir pourquoi Microsoft n'a pas emballé cela par défaut, pensez au nombre de combinaisons qu'il faudrait.

delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
delegate TResult Func<T1, T2, TResult>(out T1 obj1, T2 obj2)
delegate TResult Func<T1, T2, TResult>(T1 obj1, out T2 obj2)
delegate TResult Func<T1, T2, TResult>(out T1 obj1, out T2 obj2)

pour seulement deux paramètres. Nous n'avons même pas touché ref. Ce serait en fait encombrant et déroutant pour les développeurs.


2
Notez que la surcharge de la fonction C # ne peut pas faire la distinction entre delegate TResult Func<T1, T2, TResult>(T1 obj, T2 obj)et delegate TResult Func<T1, T2, TResult>(out T1 obj, T2 obj). Donc, outre le nombre de surcharges, le nom du symbole est une autre raison pour laquelle Microsoft n'a pas pu ajouter ces surcharges de Func.
Kasper van den Berg

Quelqu'un peut-il me référer à un article MSDN sur les délégués ci-dessus?
Su Llewellyn

@SuLlewellyn Je n'ai pas pu trouver l'article msdn d'origine, mais vous pouvez essayer: docs.microsoft.com/en-us/dotnet/api/… , docs.microsoft.com/en-us/dotnet/api/…
nawfal

0

Vous pouvez l'envelopper dans un lambda / délégué / fonction / méthode qui a exposé la bonne interface et appelé FindForBar, mais je soupçonne que FindForBar a compté comme un paramètre out comme raison, vous devez donc être sûr de jeter ces informations ok / sûr / souhaitable / a eu les bons résultats (vous devez être sûr de cela même si vous pouvez simplement passer directement dans FindForBar).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.