Was ist eine Methodengruppe in C #?

351

Ich habe häufig einen Fehler wie "Konvertieren von 'Methodengruppe' in 'Zeichenfolge'" in folgenden Fällen festgestellt:

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

Natürlich gab es in der letzten Zeile einen Tippfehler, weil ich die Aufrufklammern danach vergessen habe ToString. Die richtige Form wäre:

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

Ich habe mich jedoch gefragt, was eine Methodengruppe ist. Google ist weder eine große Hilfe noch ein MSDN .

Andrei Rînea
quelle
62
Abschnitt 7.1 der C # 3.0-Spezifikation definiert "Methodengruppe".
Eric Lippert
2
Ich habe diesen Fehler jetzt gelesen, da Sie beim Aufrufen einer Methode die Klammern verpasst haben .
Niico
2
Wenn Sie eine Liste eines geeigneten Delegatentyps gehabt hätten, z. B. var list = new List<Func<string>>();, wäre die Methodengruppe verwendbar gewesen und list.Add(someObject.ToString);hätte funktioniert.
Jeppe Stig Nielsen

Antworten:

332

Verfahren Gruppe ist der Name für eine Reihe von Methoden (das könnte nur eine sein) - also in der Theorie die ToStringMethode mehr Überlastungen kann (plus irgendwelche Erweiterungsmethoden) ToString(), ToString(string format)usw. - daher ToStringvon selbst , wird als „Methode Gruppe“.

Normalerweise kann eine Methodengruppe mithilfe der Überlastungsauflösung in einen (typisierten) Delegaten konvertiert werden - jedoch nicht in eine Zeichenfolge usw.; es macht keinen Sinn.

Sobald Sie wieder Klammern hinzufügen; Die Überlastungsauflösung setzt ein und Sie haben einen Methodenaufruf eindeutig identifiziert.

Marc Gravell
quelle
6
Was wären typische Verwendungen einer Methodengruppe? Da es (so wie ich es verstehe) denselben Namen hat, unterscheiden sich die Parameteranzahl und / oder die Typen. Sie können also mit der Gruppe nicht mehr als eine Methode aus der Methodengruppe aufrufen.
Andrei Rînea
32
Es ist lediglich ein Compilerbegriff für "Ich weiß, wie der Methodenname lautet, aber ich kenne die Signatur nicht". es existiert zur Laufzeit nicht. AFAIK, die einzige Verwendung einer Methodengruppe für sich (keine Klammern usw.) ist die Erstellung von Delegaten.
Marc Gravell
20
ECMA 334v4 §14.1: Eine Methodengruppe kann in einem Aufrufausdruck (§14.5.5), in einem Delegatenerstellungsausdruck (§14.5.10.3) verwendet oder implizit in einen kompatiblen Delegattyp konvertiert werden. In jedem anderen Kontext verursacht ein als Methodengruppe klassifizierter Ausdruck einen Fehler bei der Kompilierung.
Marc Gravell
1
Die Unterstützung von Kovarianz und Kontravarianz für Methodengruppen ermöglicht den Abgleich von Methodensignaturen mit Delegatentypen. Auf diese Weise können Sie Delegierten nicht nur Methoden zuweisen, die übereinstimmende Signaturen aufweisen, sondern auch Methoden, die mehr abgeleitete Typen (Kovarianz) zurückgeben oder Parameter akzeptieren, die weniger abgeleitete Typen (Kontravarianz) als die vom Delegatentyp angegebenen aufweisen. Weitere Informationen finden Sie unter Varianz in Delegaten (C #) und Verwenden von Varianz in Delegaten (C #).
user2211290
162

Wenn Sie LINQ verwenden, können Sie anscheinend auch so etwas tun myList.Select(methodGroup).

So habe ich zum Beispiel:

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

Anstatt die zu verwendende Variable explizit wie folgt anzugeben:

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

Ich kann den Namen der Var einfach weglassen:

public List<string> GetStringStuff()
{
    return something.getStringsFromSomewhere.Select(DoSomethingToMyString);
}
Kaeles
quelle
112
Eine ReSharper-Empfehlung hat mich veranlasst, nach Methodengruppen zu suchen. Dies ist, was ReSharper letztendlich mit einem meiner linq-Ausdrücke gemacht hat.
a_hardin
50
@a_hardin: ReSharper FTW! Dank Resharper habe ich viel über LINQ gelernt.
Jason Down
3
Die "explizitere" Version macht nur eine im Wesentlichen nutzlose Wrapper-Methode. Die anonyme Wrapper-Methode und DoSomethingToMyString nehmen beide eine Zeichenfolge und geben eine Zeichenfolge zurück. Die Zeichen "str => [...] (str)" sind nur Cruft, die der Compiler hoffentlich entfernt.
Grault
6
Der Compiler optimiert nichts. Mit ILDASM sehen Sie, dass die explizite Version eine anonyme Methode (die Lambda-Implementierung) erstellt und an Select () übergibt. Die implizite Version übergibt DoSomethingToMyString direkt.
Rolf
14
Erinnert mich an return flag == true ? true : false(Gesichtspalme).
ErikE
24

Sie können eine Methodengruppe in einen Delegaten umwandeln.

Die Delegatensignatur wählt 1 Methode aus der Gruppe aus.

In diesem Beispiel wird die ToString()Überladung ausgewählt, für die ein Zeichenfolgenparameter erforderlich ist:

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

In diesem Beispiel wird die ToString()Überlastung ausgewählt, für die keine Parameter erforderlich sind:

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

Das erste Ergebnis Ihrer MSDN-Suche lautete:

Die Methodengruppe gibt die eine aufzurufende Methode oder die Gruppe überladener Methoden an, aus denen eine bestimmte aufzurufende Methode ausgewählt werden soll

Mein Verständnis ist, dass im Grunde genommen, wenn Sie nur schreiben someInteger.ToString, es sich beziehen kann auf:

Int32.ToString(IFormatProvider) 

oder es kann sich beziehen auf:

Int32.ToString()

Daher wird es als Methodengruppe bezeichnet.

oscarkuo
quelle
18

Die ToStringFunktion hat viele Überladungen - die Methodengruppe wäre die Gruppe, die aus all den verschiedenen Überladungen für diese Funktion besteht.

1800 INFORMATIONEN
quelle
2
Ja, und der Punkt ist, dass eine Methodengruppe ein Konstrukt zur Kompilierungszeit ist. Der Compiler wählt eine Methodenüberladung entsprechend dem Kontext aus, in dem die Nachrichtengruppe verwendet wird. Zum Beispiel: Sie können nicht "var x = Foo;" schreiben. (wobei Foo eine Methodengruppe ist), lehnt der Compiler dies ab, selbst wenn nur eine Überladung vorliegt.
Rolf