Що таке група методів у C #?


351

Я часто стикався з помилкою, наприклад "не вдається перетворити з" групи методів "в" рядок "" у таких випадках:

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

звичайно, в останньому рядку була помилка друку, тому що я забув дужки виклику після ToString. Правильною формою буде:

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

Однак мені стало цікаво, що таке група методів. Google не допомагає ні MSDN .


62
Розділ 7.1 специфікації C # 3.0 визначає "групу методів".
Ерік Ліпперт

2
Я читав цю помилку зараз, коли ви пропустили дужки під час виклику методу .
niico

2
Якби у вас був список відповідного типу делегата, наприклад var list = new List<Func<string>>();, група методів була б корисною і list.Add(someObject.ToString);працювала б.
Jeppe Stig Nielsen

Відповіді:


332

Метод групи це ім'я для набору методів (які можуть бути тільки один) - тобто в теорії ToStringметод може мати кілька перевантажених (плюс будь-які методи розширення): ToString(), ToString(string format)і т.д. - отже , ToStringсаме по собі є «груповий метод».

Зазвичай він може конвертувати групу методів у (набраний) делегат, використовуючи роздільну здатність перевантаження, але не в рядок тощо; це не має сенсу.

Після додавання дужок знову починається дозвіл на перевантаження, і ви однозначно визначили виклик методу.


6
Які типові способи використання групи методів? Оскільки (так я розумію) у нього однакова назва, кількість параметрів та / або типи будуть відрізнятися. Тому ви не можете викликати більше ніж один метод із групи методів, використовуючи групу.
Андрій Ронеа

32
Це суто термін компілятора для "Я знаю, що ім'я методу, але не знаю підпису"; вона не існує в час виконання. AFAIK, єдине використання групи методів самостійно (без дужок тощо) є під час побудови делегата.
Марк Гравелл

20
§ 14.1 ECMA 334v4: Група методів може бути використана у виклику-виклику (§14.5.5), який використовується у виразі делегата-створення (§14.5.10.3), або неявно перетворений у сумісний тип делегата. У будь-якому іншому контексті вираз, класифікований як група методів, викликає помилку часу компіляції.
Marc Gravell

1
Підтримка коваріації та противаріантності груп методів дозволяє узгодити підписи методів із типами делегата. Це дає змогу призначити делегатам не тільки методи, що мають відповідні підписи, але й методи, які повертають більш похідні типи (коваріантність) або приймають параметри, які мають менш похідні типи (контраваріантність), ніж ті, які визначені типом делегата. Для отримання додаткових відомостей див. «Варіант у делегатах» (C #) та «Використання варіації в делегатах» (C #).
user2211290

162

Крім того, якщо ви використовуєте LINQ, ви, очевидно, можете зробити щось на кшталт myList.Select(methodGroup).

Так, наприклад, у мене є:

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

Замість того, щоб чітко вказати змінну, яку слід використовувати так:

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

Я можу просто опустити ім’я var:

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

112
Рекомендація ReSharper - це те, що спонукало мене до пошуку групи методів. Так закінчився ReSharper в одному з моїх виразів linq.
a_hardin

50
@a_hardin: ReSharper FTW! Я дізнався багато про LINQ завдяки Resharper.
Jason Down

3
"Більш чітка" версія лише робить принципово марним обгортковий метод. Метод анонімної обгортки та DoSomethingToMyString беруть рядок та повертають рядок. Символи "str => [...] (str)" - просто чіткі, які компілятор сподівається оптимізувати.
Граль

6
Компілятор нічого не оптимізує. Використовуючи ILDASM, ви бачите, що явна версія створює анонімний метод (лямбда-реалізація) і передає його в Select (). Неявна версія передає DoSomethingToMyString безпосередньо.
Рольф

14
Нагадує мені return flag == true ? true : false(facepalm).
ЕрікЕ

24

Ви можете призначити групу методів делегатом.

Підпис делегата вибирає 1 метод із групи.

У цьому прикладі вибирається ToString()перевантаження, яка приймає параметр рядка:

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

У цьому прикладі вибирається ToString()перевантаження, яка не приймає жодних параметрів:

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

21

Перший результат у вашому пошуку MSDN сказав:

Група методів ідентифікує один метод виклику або набір перевантажених методів, з яких вибрати конкретний метод для виклику

моє розуміння - це в основному тому, що коли ви просто пишете someInteger.ToString, це може стосуватися:

Int32.ToString(IFormatProvider) 

або це може стосуватися:

Int32.ToString()

тому його називають групою методів.


18

ToStringФункція має багато перевантажень - група методу буде група , що складається з усіх різних перевантажень для цієї функції.


2
Так, і справа в тому, що група методів - це конструкція часу компіляції. Компілятор вибирає один метод перевантаження відповідно до контексту, де використовується група повідомлень. Наприклад: ви не можете написати "var x = Foo;" (де Foo - група методів), компілятор відкидає це, навіть якщо є лише одна перевантаження.
Рольф
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.