web-dev-qa-db-fra.com

Quelle est la différence entre Func <chaîne, chaîne> et délégué?

Je vois les délégués sous deux formes:

A. Func<string, string> convertMethod = lambda 

B. public delegate string convertMethod(string value);

Je ne sais pas vraiment quelle est la différence entre ces deux. Sont-ils tous les deux délégués? Je crois que le premier utiliserait un lambda et le second devrait avoir une méthode pour effectuer réellement le travail. Je peux aussi être confus.

71
Dietpixel

Tout d'abord, vos deux exemples font deux choses totalement distinctes. La première consiste à déclarer une variable déléguée générique et à lui affecter une valeur, la seconde ne fait que définir un type delegate. Votre exemple, plus complètement, serait:

public static class Program
{
    // you can define your own delegate for a Nice meaningful name, but the
    // generic delegates (Func, Action, Predicate) are all defined already
    public delegate string ConvertedMethod(string value);

    public static void Main()
    {
        // both work fine for taking methods, lambdas, etc.
        Func<string, string> convertedMethod = s => s + ", Hello!";
        ConvertedMethod convertedMethod2 = s => s + ", Hello!";
    }
}

Mais plus précisément, Func<string,string> Et delegate string convertMethod(string) seraient capables de contenir les mêmes définitions de méthode, qu'il s'agisse de méthodes, de méthodes anonymes ou d'expressions lambda.

Quant à ce que vous devez utiliser, cela dépend de la situation. Si vous voulez que votre délégué soit défini davantage par ce qu'il prend et retourne, les délégués génériques sont parfaits. Si vous voulez que le délégué ait un nom spécial qui donne plus de définition de ce que ce délégué doit faire (au-delà du simple Action, Predicate, etc.), la création de votre propre délégué est toujours une option.

61
James Michael Hare

L'exemple de code que vous avez est un peu confus, alors laissez-moi essayer de le clarifier. Les 2 éléments suivants sont des déclarations de délégué. Celles-ci sont faciles à repérer car elles contiendront toujours le mot clé delegate

public delegate TReturn Func<TArg, TReturn>(Targ value);
public delegate string convertMethod(string value);

Cette ligne de code attribue une valeur à un local qui est tapé à un délégué

Func<string, string> local = lambda;

Cependant, le code ci-dessus n'est pas limité à l'utilisation de lambdas uniquement. La valeur peut également être un groupe de méthodes compatible ou une autre valeur de délégué.

Un autre élément à noter est que même si Func<string, string> et convertMethod sont tous deux des délégués avec des signatures identiques, leurs valeurs sont pas convertibles entre elles. Par exemple, ce qui suit est illégal

Func<string, string> local1 = ...;
convertMethod local2 = local1; // Error!!!
12
JaredPar

De MSDN ,

Dans les versions de C # antérieures à 2.0, la seule façon de déclarer un délégué était d'utiliser des méthodes nommées. C # 2.0 a introduit des méthodes anonymes et en C # 3.0 et versions ultérieures, les expressions lambda remplacent les méthodes anonymes comme moyen préféré d'écrire du code en ligne.

et

Il existe un cas dans lequel une méthode anonyme fournit des fonctionnalités introuvables dans les expressions lambda. Les méthodes anonymes vous permettent d'omettre la liste des paramètres. Cela signifie qu'une méthode anonyme peut être convertie en délégués avec une variété de signatures.

Vous pouvez également être intéressé par cette SO sur mot-clé délégué vs expression lambda .

De plus, MSDN a un bon article sur les expressions Lambda :

delegate int del(int i);
static void Main(string[] args)
{
    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25
}

Dans l'exemple précédent, notez que la signature du délégué a un paramètre d'entrée implicitement typé de type int et renvoie un int. L'expression lambda peut être convertie en délégué de ce type car elle a également un paramètre d'entrée (x) et une valeur de retour que le compilateur peut implicitement convertir en type int. (L'inférence de type est discutée plus en détail dans les sections suivantes.) Lorsque le délégué est appelé en utilisant un paramètre d'entrée de 5, il renvoie un résultat de 25.

8
user195488

A initialise une instance d'un délégué (qui peut être appelée immédiatement). C'est une variable de type Func <chaîne, chaîne>.

B spécifie la définition d'un délégué (sa signature). Il peut être utilisé pour définir ultérieurement des variables de type convertMethod .

4
fparadis2