Qu'est-ce qu'un groupe de méthodes en C #?

351

J'ai souvent rencontré une erreur telle que "impossible de convertir de 'groupe de méthodes' en 'chaîne'" dans des cas comme:

var list = new List<string>();
// ... snip
list.Add(someObject.ToString);

bien sûr, il y avait une faute de frappe dans la dernière ligne parce que j'ai oublié les parenthèses d'invocation après ToString. La forme correcte serait:

var list = new List<string>();
// ... snip
list.Add(someObject.ToString()); // <- notice the parentheses

Cependant, je me suis demandé ce qu'est un groupe de méthodes. Google n'est pas une grande aide ni MSDN .

Andrei Rînea
la source
62
La section 7.1 de la spécification C # 3.0 définit le "groupe de méthodes".
Eric Lippert
2
J'ai lu cette erreur maintenant car vous avez raté les crochets lors de l'appel d'une méthode .
niico
2
Si vous aviez eu une liste d'un type de délégué approprié, tel que var list = new List<Func<string>>();, alors le groupe de méthodes aurait été utilisable et list.Add(someObject.ToString);aurait fonctionné.
Jeppe Stig Nielsen

Réponses:

332

Un groupe de méthode est le nom d'un ensemble de méthodes (qui pourrait être juste un) - à savoir , en théorie , la ToStringméthode peut avoir plusieurs surcharges (plus les méthodes d'extension): ToString(), ToString(string format), etc - donc ToStringpar lui - même est un « groupe de méthode ».

Il peut généralement convertir un groupe de méthodes en délégué (typé) en utilisant la résolution de surcharge - mais pas en chaîne, etc. ça n'a pas de sens.

Une fois que vous ajoutez des parenthèses, encore une fois; la résolution de surcharge entre en jeu et vous avez identifié sans ambiguïté un appel de méthode.

Marc Gravell
la source
6
Quelles seraient les utilisations typiques d'un groupe de méthodes? Puisque (donc je comprends), il porte le même nom, le nombre de paramètres et / ou les types différeront. Vous ne pouvez donc pas invoquer plus d'une méthode du groupe de méthodes à l'aide du groupe.
Andrei Rînea
32
Il s'agit purement d'un terme de compilateur pour "Je sais quel est le nom de la méthode, mais je ne connais pas la signature"; il n'a pas d'existence au moment de l'exécution. AFAIK, la seule utilisation d'un groupe de méthodes en lui- même (pas de crochets, etc.) est pendant la construction du délégué.
Marc Gravell
20
ECMA 334v4 §14.1: Un groupe de méthodes peut être utilisé dans une expression d'invocation (§14.5.5), utilisé dans une expression de création de délégué (§14.5.10.3), ou implicitement converti en un type de délégué compatible. Dans tout autre contexte, une expression classée comme groupe de méthodes provoque une erreur au moment de la compilation.
Marc Gravell
1
La prise en charge de la covariance et de la contravariance pour les groupes de méthodes permet de faire correspondre les signatures de méthode avec les types de délégué. Cela vous permet d'affecter aux délégués non seulement des méthodes qui ont des signatures correspondantes, mais aussi des méthodes qui renvoient plus de types dérivés (covariance) ou qui acceptent des paramètres qui ont moins de types dérivés (contravariance) que ceux spécifiés par le type délégué. Pour plus d'informations, consultez Variance dans les délégués (C #) et Utilisation de la variance dans les délégués (C #).
user2211290
162

De plus, si vous utilisez LINQ, vous pouvez apparemment faire quelque chose comme myList.Select(methodGroup).

Ainsi, par exemple, j'ai:

private string DoSomethingToMyString(string input)
{
    // blah
}

Au lieu d'indiquer explicitement la variable à utiliser comme ceci:

public List<string> GetStringStuff()
{
    return something.getStringsFromSomewhere.Select(str => DoSomethingToMyString(str));
}

Je peux simplement omettre le nom du var:

public List<string> GetStringStuff()
{
    return something.getStringsFromSomewhere.Select(DoSomethingToMyString);
}
Kaeles
la source
112
Une recommandation ReSharper est ce qui m'a amené à rechercher un groupe de méthodes. C'est ce que ReSharper a fini par faire pour l'une de mes expressions linq.
a_hardin
50
@a_hardin: ReSharper FTW! J'ai beaucoup appris sur LINQ grâce à Resharper.
Jason Down
3
La version "plus explicite" ne fait qu'une méthode de wrapper essentiellement inutile. La méthode d'encapsuleur anonyme et DoSomethingToMyString prennent toutes deux une chaîne et retournent une chaîne. Les caractères "str => [...] (str)" sont juste croustillants que le compilateur optimise, espérons-le.
Grault
6
Le compilateur n'optimise rien. À l'aide d'ILDASM, vous voyez que la version explicite crée une méthode anonyme (l'implémentation lambda) et la transmet à Select (). La version implicite transmet directement DoSomethingToMyString.
Rolf
14
Ça me rappelle return flag == true ? true : false(facepalm).
ErikE
24

Vous pouvez convertir un groupe de méthodes en délégué.

La signature du délégué sélectionne 1 méthode parmi le groupe.

Cet exemple sélectionne la ToString()surcharge qui prend un paramètre de chaîne:

Func<string,string> fn = 123.ToString;
Console.WriteLine(fn("00000000"));

Cet exemple sélectionne la ToString()surcharge qui ne prend aucun paramètre:

Func<string> fn = 123.ToString;
Console.WriteLine(fn());
Jack
la source
21

Le premier résultat de votre recherche MSDN indique:

Le groupe de méthodes identifie la méthode à invoquer ou l'ensemble de méthodes surchargées à partir desquelles choisir une méthode spécifique à invoquer

ma compréhension est que, fondamentalement, parce que lorsque vous écrivez someInteger.ToString, cela peut faire référence à:

Int32.ToString(IFormatProvider) 

ou il peut se référer à:

Int32.ToString()

il est donc appelé un groupe de méthodes.

oscarkuo
la source
18

La ToStringfonction a de nombreuses surcharges - le groupe de méthodes serait le groupe composé de toutes les différentes surcharges pour cette fonction.

1800 INFORMATION
la source
2
Oui, et le fait est qu'un groupe de méthodes est une construction au moment de la compilation. Le compilateur choisit une méthode de surcharge en fonction du contexte dans lequel le groupe de messages est utilisé. Par exemple: vous ne pouvez pas écrire "var x = Foo;" (où Foo est un groupe de méthodes), le compilateur rejette cela même s'il n'y a qu'une seule surcharge.
Rolf