O que é um grupo de métodos em C #?


351

Eu sempre encontrei um erro como "não é possível converter de 'grupo de métodos' para 'string'" em casos como:

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

é claro que houve um erro de digitação na última linha porque esqueci os parênteses de invocação depois ToString. A forma correta seria:

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

No entanto, eu me perguntei o que é um grupo de métodos. O Google não ajuda muito nem o MSDN .


62
A seção 7.1 da especificação do C # 3.0 define "grupo de métodos".
22630 Eric Lippert

2
Eu li esse erro agora, pois você perdeu os colchetes ao chamar um método .
Niico 23/11

2
Se você tivesse uma lista de um tipo de delegado apropriado, como, por exemplo var list = new List<Func<string>>();, o grupo de métodos teria sido utilizável e list.Add(someObject.ToString);funcionaria.
Jeppe Stig Nielsen

Respostas:


332

Um grupo método é o nome de um conjunto de métodos (que pode ser apenas uma) - ou seja, em teoria, o ToStringmétodo pode ter múltiplos sobrecargas (além de quaisquer métodos de extensão): ToString(), ToString(string format), etc -, portanto, ToStringpor si só é um "grupo método".

Geralmente, ele pode converter um grupo de métodos em um delegado (digitado) usando a resolução de sobrecarga - mas não em uma string etc; isso não faz sentido.

Depois de adicionar parênteses, novamente; a resolução de sobrecarga entra em ação e você identificou inequivocamente uma chamada de método.


6
Quais seriam os usos típicos de um grupo de métodos? Como (pelo que entendi) ele tem o mesmo nome, a contagem de parâmetros e / ou os tipos serão diferentes. Portanto, você não pode chamar mais de um método do grupo de métodos usando o grupo
Andrei Rînea

32
É um termo puramente compilador para "Eu sei qual é o nome do método, mas não sei a assinatura"; não existe no tempo de execução. AFAIK, o único uso de um grupo de métodos por si só (sem colchetes etc.) é durante a construção do delegado.
Marc Gravell

20
ECMA 334v4 §14.1: Um grupo de métodos pode ser usado em uma expressão de invocação (§14.5.5), usado em uma expressão de criação de delegado (§14.5.10.3) ou convertido implicitamente em um tipo de delegado compatível. Em qualquer outro contexto, uma expressão classificada como um grupo de métodos causa um erro em tempo de compilação.
Marc Gravell

11
O suporte de covariância e contravariância para grupos de métodos permite a correspondência de assinaturas de métodos com tipos de delegados. Isso permite atribuir aos delegados não apenas métodos que possuem assinaturas correspondentes, mas também métodos que retornam mais tipos derivados (covariância) ou que aceitam parâmetros com menos tipos derivados (contravariância) do que os especificados pelo tipo de delegado. Para obter mais informações, consulte Variação em delegados (C #) e Usando variação em delegados (C #).
user2211290

162

Além disso, se você estiver usando o LINQ, aparentemente poderá fazer algo parecido myList.Select(methodGroup).

Então, por exemplo, eu tenho:

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

Em vez de declarar explicitamente a variável a ser usada assim:

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

Eu posso simplesmente omitir o nome do var:

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

112
Uma recomendação do ReSharper foi o que me levou a procurar um grupo de métodos. Foi isso que o ReSharper acabou fazendo em uma das minhas expressões linq.
a_hardin

50
@a_hardin: ReSharper FTW! Eu aprendi muito sobre o LINQ graças ao Resharper.
Jason Down

3
A versão "mais explícita" está apenas criando um método de invólucro essencialmente inútil. O método de invólucro anônimo e DoSomethingToMyString pegam uma sequência e retornam uma sequência. Os caracteres "str => [...] (str)" são apenas elementos que esperamos que o compilador otimize.
Grault 18/03/13

6
O compilador não otimiza nada. Usando o ILDASM, você vê que a versão explícita cria um método anônimo (a implementação lambda) e o passa para Select (). A versão implícita passa DoSomethingToMyString diretamente.
Rolf

14
Lembra-me de return flag == true ? true : false(facepalm).
21415 ErikE em:

24

Você pode converter um grupo de métodos em um delegado.

A assinatura do delegado seleciona 1 método do grupo.

Este exemplo seleciona a ToString()sobrecarga que recebe um parâmetro de string:

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

Este exemplo seleciona a ToString()sobrecarga que não aceita parâmetros:

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

21

O primeiro resultado na sua pesquisa do MSDN disse:

O grupo de métodos identifica o único método a ser chamado ou o conjunto de métodos sobrecarregados para escolher um método específico a ser chamado.

meu entendimento é que basicamente porque quando você escreve someInteger.ToString, pode se referir a:

Int32.ToString(IFormatProvider) 

ou pode se referir a:

Int32.ToString()

por isso é chamado de grupo de métodos.


18

A ToStringfunção tem muitas sobrecargas - o grupo de métodos seria o grupo que consiste em todas as diferentes sobrecargas para essa função.


2
Sim, e o ponto é que um grupo de métodos é uma construção em tempo de compilação. O compilador escolhe uma sobrecarga de método de acordo com o contexto em que o grupo de mensagens é usado. Por exemplo: você não pode escrever "var x = Foo;" (onde Foo é um grupo de métodos), o compilador rejeita isso mesmo se houver apenas uma sobrecarga.
Rolf
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.