Co to jest grupa metod w języku C #?


351

Często napotykałem błąd, taki jak „nie można przekonwertować z„ grupy metod ”na„ ciąg ”w przypadkach takich jak:

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

oczywiście w ostatniej linii była literówka, ponieważ później zapomniałem nawiasów wywołania ToString. Prawidłowa forma to:

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

Zastanawiałem się jednak, co to jest grupa metod. Google nie jest ani pomocą, ani MSDN .


62
Sekcja 7.1.1 specyfikacji C # 3.0 definiuje „grupę metod”.
Eric Lippert,

2
Przeczytałem teraz ten błąd, ponieważ pominąłeś brak nawiasów podczas wywoływania metody .
niico

2
Gdybyś miał listę odpowiedniego typu delegata, na przykład var list = new List<Func<string>>();, grupa metod byłaby użyteczna i list.Add(someObject.ToString);działałaby.
Jeppe Stig Nielsen

Odpowiedzi:


332

Grupa metoda jest nazwa dla zestawu metod (to może być tylko jeden) - czyli teoretycznie ToStringmetoda może mieć wiele przeciążeniem (plus wszelkie metody rozszerzenie) ToString(), ToString(string format)itp - stąd ToStringsama jest „grupa metoda”.

Zwykle może konwertować grupę metod na (typowanego) delegata przy użyciu rozwiązania przeciążenia - ale nie do ciągu itp .; to nie ma sensu.

Po dodaniu nawiasów ponownie; włącza się rozdzielczość przeciążenia i jednoznacznie zidentyfikowano wywołanie metody.


6
Jakie byłyby typowe zastosowania grupy metod? Ponieważ (jak rozumiem) ma tę samą nazwę, liczba parametrów i / lub typy będą się różnić. Dlatego nie można wywoływać więcej niż jednej metody z grupy metod przy użyciu grupy.
Andrei Rînea

32
Jest to termin wyłącznie kompilatorowy na „Wiem, jak brzmi nazwa metody, ale nie znam podpisu”; nie istnieje w czasie wykonywania. AFAIK, jedynym zastosowaniem samej grupy metod (bez nawiasów itp.) Jest budowa delegata.
Marc Gravell

20
ECMA 334v4 §14.1: Grupa metod może być użyta w wyrażeniu wywołania (§14.5.5), użytym w wyrażeniu tworzenia delegata (§14.5.10.3) lub pośrednio przekonwertowana na zgodny typ delegowanego. W dowolnym innym kontekście wyrażenie sklasyfikowane jako grupa metod powoduje błąd kompilacji.
Marc Gravell

1
Obsługa kowariancji i kontrawariancji dla grup metod pozwala na dopasowanie sygnatur metod do typów delegowanych. Umożliwia to przypisanie do delegatów nie tylko metod, które mają pasujące podpisy, ale także metod, które zwracają więcej typów pochodnych (kowariancja) lub które akceptują parametry, które mają mniej pochodnych typów (kontrawariancja) niż te określone przez typ delegata. Aby uzyskać więcej informacji, zobacz Odchylenie w delegatach (C #) i Korzystanie z odchylenia w delegatach (C #).
user2211290,

162

Ponadto, jeśli używasz LINQ, możesz najwyraźniej zrobić coś takiego myList.Select(methodGroup).

Na przykład mam:

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

Zamiast jawnego podania zmiennej, która ma być używana w następujący sposób:

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

Mogę po prostu pominąć nazwę var:

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

112
Polecenie ReSharper skłoniło mnie do wyszukania grupy metod. To właśnie zrobił ReSharper z jednym z moich wyrażeń linq.
a_hardin

50
@a_hardin: ReSharper FTW! Wiele się nauczyłem o LINQ dzięki Resharper.
Jason Down

3
„Bardziej wyraźna” wersja czyni jedynie zasadniczo bezużyteczną metodę otoki. Anonimowa metoda opakowania i DoSomethingToMyString pobierają ciąg i zwracają ciąg. Znaki „str => [...] (str)” są po prostu cruft, które kompilator ma nadzieję zoptymalizować.
Grault

6
Kompilator niczego nie optymalizuje. Za pomocą ILDASM widać, że jawna wersja tworzy anonimową metodę (implementacja lambda) i przekazuje ją do Select (). Wersja niejawna przekazuje DoSomethingToMyString bezpośrednio.
Rolf

14
Przypomina mi return flag == true ? true : false(facepalm).
ErikE

24

Możesz rzutować grupę metod na delegata.

Podpis delegata wybiera 1 metodę z grupy.

W tym przykładzie wybrano ToString()przeciążenie, które pobiera parametr ciągu:

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

W tym przykładzie wybrano ToString()przeciążenie, które nie przyjmuje parametrów:

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

21

Pierwszy wynik wyszukiwania MSDN powiedział:

Grupa metod identyfikuje jedną metodę do wywołania lub zestaw przeciążonych metod, spośród których można wybrać konkretną metodę do wywołania

rozumiem to po prostu dlatego, że po prostu piszesz someInteger.ToString, może odnosić się do:

Int32.ToString(IFormatProvider) 

lub może odnosić się do:

Int32.ToString()

nazywa się to grupą metod.


18

ToStringFunkcja ma wiele przeciążeń - grupa metodą jest z grupy składającej się ze wszystkich różnych przeciążeniem dla tej funkcji.


2
Tak, chodzi o to, że grupa metod jest konstrukcją czasu kompilacji. Kompilator wybiera przeciążenie jednej metody zgodnie z kontekstem, w którym używana jest grupa komunikatów. Na przykład: nie możesz napisać „var x = Foo;” (gdzie Foo jest grupą metod), kompilator odrzuca to, nawet jeśli występuje tylko jedno przeciążenie.
Rolf
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.