Що таке група методів у 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.