¿Qué es un grupo de métodos en C #?

351

A menudo he encontrado un error como "no se puede convertir de 'grupo de métodos' a 'cadena'" en casos como:

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

por supuesto, hubo un error tipográfico en la última línea porque olvidé los paréntesis de invocación después ToString. La forma correcta sería:

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

Sin embargo, llegué a preguntarme qué es un grupo de métodos. Google no es de gran ayuda ni MSDN .

Andrei Rînea
fuente
6262
La sección 7.1 de la especificación C # 3.0 define "grupo de métodos".
Eric Lippert
2
Leí este error ahora, ya que te perdiste los corchetes al llamar a un método .
niico
2
Si hubiera tenido una lista de un tipo de delegado apropiado, como var list = new List<Func<string>>();, entonces el grupo de métodos habría sido utilizable y list.Add(someObject.ToString);habría funcionado.
Jeppe Stig Nielsen

Respuestas:

332

Un grupo método es el nombre para un conjunto de métodos (que podría ser sólo uno) - es decir, en teoría, el ToStringmétodo puede tener múltiples sobrecargas (además de cualquiera de los métodos de extensión): ToString(), ToString(string format), etc - por lo tanto ToStringpor sí mismo es un "grupo de método".

Por lo general, puede convertir un grupo de métodos en un delegado (tipado) utilizando la resolución de sobrecarga, pero no en una cadena, etc. No tiene sentido.

Una vez que agregue paréntesis, nuevamente; se activa la resolución de sobrecarga y ha identificado inequívocamente una llamada a un método.

Marc Gravell
fuente
66
¿Cuáles serían los usos típicos de un grupo de métodos? Como (según tengo entendido) tiene el mismo nombre, el recuento de parámetros y / o los tipos serán diferentes. Por lo tanto, no puede invocar más de un método del grupo de métodos utilizando el grupo
Andrei Rînea
32
Es puramente un término compilador para "Sé cuál es el nombre del método, pero no sé la firma"; no tiene existencia en tiempo de ejecución. AFAIK, el único uso de un grupo de métodos por sí mismo (sin paréntesis, etc.) es durante la construcción del delegado.
Marc Gravell
20
ECMA 334v4 §14.1: Un grupo de métodos se puede usar en una expresión de invocación (§14.5.5), en una expresión de creación de delegado (§14.5.10.3) o se puede convertir implícitamente a un tipo de delegado compatible. En cualquier otro contexto, una expresión clasificada como un grupo de métodos provoca un error en tiempo de compilación.
Marc Gravell
1
El soporte de covarianza y contravarianza para grupos de métodos permite hacer coincidir las firmas de métodos con los tipos de delegados. Esto le permite asignar a los delegados no solo métodos que tienen firmas coincidentes, sino también métodos que devuelven más tipos derivados (covarianza) o que aceptan parámetros que tienen menos tipos derivados (contravarianza) que los especificados por el tipo delegado. Para obtener más información, consulte Varianza en delegados (C #) y Uso de varianza en delegados (C #).
user2211290
162

Además, si está utilizando LINQ, aparentemente puede hacer algo como myList.Select(methodGroup).

Entonces, por ejemplo, tengo:

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

En lugar de indicar explícitamente la variable que se utilizará así:

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

Solo puedo omitir el nombre de la var:

public List<string> GetStringStuff()
{
    return something.getStringsFromSomewhere.Select(DoSomethingToMyString);
}
Kaeles
fuente
112
Una recomendación de ReSharper es lo que me llevó a buscar un grupo de métodos. Esto es lo que ReSharper terminó haciendo en una de mis expresiones linq.
a_hardin
50
@a_hardin: ReSharper FTW! Aprendí mucho sobre LINQ gracias a Resharper.
Jason Down
3
La versión "más explícita" solo está haciendo un método envoltorio esencialmente inútil. El método de contenedor anónimo y DoSomethingToMyString toman una cadena y devuelven una cadena. Los caracteres "str => [...] (str)" son simplemente crujientes que el compilador, con suerte, optimiza.
Grault
66
El compilador no optimiza nada. Usando ILDASM, verá que la versión explícita crea un método anónimo (la implementación lambda) y lo pasa a Select (). La versión implícita pasa DoSomethingToMyString directamente.
Rolf
14
Me recuerda a return flag == true ? true : false(facepalm).
ErikE
24

Puede convertir un grupo de métodos en un delegado.

La firma del delegado selecciona 1 método del grupo.

Este ejemplo selecciona la ToString()sobrecarga que toma un parámetro de cadena:

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

Este ejemplo selecciona la ToString()sobrecarga que no toma parámetros:

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

El primer resultado en su búsqueda de MSDN dijo:

El grupo de métodos identifica el único método para invocar o el conjunto de métodos sobrecargados para elegir un método específico para invocar

Entiendo que, básicamente, porque cuando escribes someInteger.ToString, puede referirse a:

Int32.ToString(IFormatProvider) 

o puede referirse a:

Int32.ToString()

por eso se llama un grupo de métodos.

oscarkuo
fuente
18

La ToStringfunción tiene muchas sobrecargas: el grupo de métodos sería el grupo que consta de todas las sobrecargas diferentes para esa función.

1800 INFORMACIÓN
fuente
2
Sí, y el punto es que un grupo de métodos es una construcción en tiempo de compilación. El compilador elige una sobrecarga de método de acuerdo con el contexto donde se usa el grupo de mensajes. Por ejemplo: no puedes escribir "var x = Foo;" (donde Foo es un grupo de métodos), el compilador rechaza esto incluso si solo hay una sobrecarga.
Rolf