Che cos'è un gruppo di metodi in C #?


351

Ho riscontrato spesso un errore come "impossibile convertire da 'gruppo di metodi' in 'stringa'" in casi come:

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

ovviamente c'era un errore di battitura nell'ultima riga perché dopo ho dimenticato le parentesi di invocazione ToString. La forma corretta sarebbe:

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

Tuttavia sono arrivato a chiedermi cosa sia un gruppo di metodi. Google non è di grande aiuto né MSDN .


62
La sezione 7.1 della specifica C # 3.0 definisce "gruppo di metodi".
Eric Lippert,

2
Ho letto questo errore ora poiché hai perso le parentesi quando hai chiamato un metodo .
Niico,

2
Se avessi avuto un elenco di un tipo delegato appropriato, ad esempio var list = new List<Func<string>>();, il gruppo di metodi sarebbe stato utilizzabile e list.Add(someObject.ToString);avrebbe funzionato.
Jeppe Stig Nielsen,

Risposte:


332

Un gruppo metodo è il nome di una serie di metodi (che potrebbe essere solo uno) - cioè in teoria il ToStringmetodo può avere più sovraccarichi (più eventuali metodi di estensione): ToString(), ToString(string format)ecc - quindi ToStringdi per sé è un "gruppo metodo".

Di solito può convertire un gruppo di metodi in un delegato (tipizzato) usando la risoluzione di sovraccarico, ma non in una stringa ecc .; non ha senso.

Dopo aver aggiunto le parentesi, di nuovo; la risoluzione di sovraccarico si avvia e l'utente ha identificato in modo inequivocabile una chiamata di metodo.


6
Quali sarebbero gli usi tipici di un gruppo di metodi? Poiché (quindi ho capito) ha lo stesso nome, il conteggio dei parametri e / o i tipi differiranno. Quindi non è possibile richiamare più di un metodo dal gruppo di metodi utilizzando il gruppo.
Andrei Rînea,

32
È puramente un termine del compilatore per "Conosco il nome del metodo, ma non conosco la firma"; non ha esistenza in fase di esecuzione. AFAIK, l'unico uso di un gruppo di metodi da solo (senza parentesi ecc.) È durante la costruzione dei delegati.
Marc Gravell

20
ECMA 334v4 §14.1: un gruppo di metodi può essere utilizzato in un'espressione di invocazione (§14.5.5), utilizzato in un'espressione di creazione di un delegato (§14.5.10.3) o convertito implicitamente in un tipo di delegato compatibile. In qualsiasi altro contesto, un'espressione classificata come gruppo di metodi provoca un errore di compilazione.
Marc Gravell

1
Il supporto di covarianza e contravarianza per i gruppi di metodi consente di abbinare le firme dei metodi con i tipi delegati. Ciò consente di assegnare ai delegati non solo metodi con firme corrispondenti, ma anche metodi che restituiscono più tipi derivati ​​(covarianza) o che accettano parametri con tipi meno derivati ​​(contravarianza) rispetto a quelli specificati dal tipo delegato. Per ulteriori informazioni, vedere Varianza nei delegati (C #) e Uso della varianza nei delegati (C #).
user2211290

162

Inoltre, se stai usando LINQ, apparentemente puoi fare qualcosa del genere myList.Select(methodGroup).

Quindi, per esempio, ho:

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

Invece di dichiarare esplicitamente la variabile da utilizzare in questo modo:

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

Posso solo omettere il nome del var:

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

112
Una raccomandazione ReSharper è ciò che mi ha portato a cercare un gruppo di metodi. Questo è ciò che ReSharper ha finito per fare con una delle mie espressioni linq.
a_hardin,

50
@a_hardin: ReSharper FTW! Ho imparato molto su LINQ grazie a Resharper.
Jason Down,

3
La versione "più esplicita" sta solo creando un metodo wrapper essenzialmente inutile. Il metodo wrapper anonimo e DoSomethingToMyString accettano entrambi una stringa e restituiscono una stringa. I caratteri "str => [...] (str)" sono solo innesti che il compilatore si spera ottimizzi.
Grault,

6
Il compilatore non ottimizza nulla. Usando ILDASM, vedi che la versione esplicita crea un metodo anonimo (l'implementazione lambda) e lo passa a Select (). La versione implicita passa direttamente DoSomethingToMyString.
Rolf,

14
Mi ricorda di return flag == true ? true : false(facepalm).
ErikE,

24

È possibile eseguire il cast di un gruppo di metodi in un delegato.

La firma del delegato seleziona 1 metodo fuori dal gruppo.

In questo esempio viene selezionato il ToString()sovraccarico che accetta un parametro stringa:

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

In questo esempio viene selezionato il ToString()sovraccarico che non accetta parametri:

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

21

Il primo risultato nella tua ricerca MSDN ha detto:

Il gruppo di metodi identifica un metodo da invocare o l'insieme di metodi sovraccaricati da cui scegliere un metodo specifico da invocare

la mia comprensione è che fondamentalmente perché quando scrivi someInteger.ToString, potrebbe riferirsi a:

Int32.ToString(IFormatProvider) 

oppure può riferirsi a:

Int32.ToString()

quindi si chiama un gruppo di metodi.


18

La ToStringfunzione ha molti sovraccarichi: il gruppo del metodo sarebbe il gruppo costituito da tutti i diversi sovraccarichi per quella funzione.


2
Sì, e il punto è che un gruppo di metodi è un costrutto in fase di compilazione. Il compilatore sceglie un overload del metodo in base al contesto in cui viene utilizzato il gruppo di messaggi. Ad esempio: non puoi scrivere "var x = Foo;" (dove Foo è un gruppo di metodi), il compilatore lo rifiuta anche se c'è un solo sovraccarico.
Rolf,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.