Qual è la differenza tra Func e delegato?

Vedo i delegati in due forms:

A. Func convertMethod = lambda B. public delegate string convertMethod(string value); 

Non sono sicuro di quale sia effettivamente la differenza tra questi due. Sono entrambi delegati? Credo che il primo userebbe un lambda e il secondo dovrebbe avere un metodo per eseguire effettivamente il lavoro. Posso anche essere confuso.

Prima di tutto, i tuoi due esempi stanno facendo due cose completamente separate. Il primo sta dichiarando una variabile delegata generica e assegnandogli un valore, la seconda sta semplicemente definendo un tipo delegate . Il tuo esempio, più completamente, sarebbe:

 public static class Program { // you can define your own delegate for a nice meaningful name, but the // generic delegates (Func, Action, Predicate) are all defined already public delegate string ConvertedMethod(string value); public static void Main() { // both work fine for taking methods, lambdas, etc. Func convertedMethod = s => s + ", Hello!"; ConvertedMethod convertedMethod2 = s => s + ", Hello!"; } } 

Ma più al punto, sia Func e delegate string convertMethod(string) sarebbe in grado di mantenere le stesse definizioni di metodo sia che si tratti di metodi, metodi anonimi o espressioni lambda.

Per quanto riguarda il quale dovresti usare, dipende dalla situazione. Se vuoi che il tuo delegato sia definito più da quello che prende e restituisce, allora i delegati generici sono perfetti. Se si desidera che il delegato abbia un nome speciale che dia più definizione di ciò che il delegato dovrebbe fare (oltre la semplice Action , Predicate , ecc.), La creazione del proprio delegato è sempre un’opzione.

L’esempio di codice che hai confonde un po ‘le cose, quindi lascia che provi a chiarirlo. I seguenti 2 articoli sono dichiarazioni delegate. Questi sono facili da individuare perché contengono sempre la parola chiave delegate

 public delegate TReturn Func(Targ value); public delegate string convertMethod(string value); 

Questa riga di codice assegna un valore a un locale che viene digitato su un delegato

 Func local = lambda; 

Il codice di cui sopra non è limitato all’utilizzo di solo lambda però. Il valore potrebbe anche essere un gruppo di metodi compatibile o un altro valore delegato.

Un altro elemento da notare è che anche se Func e convertMethod sono entrambi delegati con firme identiche, i loro valori non sono convertibili l’uno con l’altro. Ad esempio il seguente è illegale

 Func local1 = ...; convertMethod local2 = local1; // Error!!! 

Da MSDN ,

Nelle versioni di C # precedenti alla 2.0, l’unico modo per dichiarare un delegato era utilizzare metodi denominati. C # 2.0 ha introdotto metodi anonimi e in C # 3.0 e versioni successive, le espressioni lambda sostituiscono metodi anonimi come il modo preferito per scrivere codice inline.

e

Esiste un caso in cui un metodo anonimo fornisce funzionalità non rilevate nelle espressioni lambda. I metodi anonimi consentono di omettere l’elenco dei parametri. Ciò significa che un metodo anonimo può essere convertito in delegati con una varietà di firme.

Potresti anche essere interessato a questa risposta SO sull’espressione parola chiave delegata vs lambda .

Inoltre, MSDN ha un buon articolo su Lambda Expressions :

 delegate int del(int i); static void Main(string[] args) { del myDelegate = x => x * x; int j = myDelegate(5); //j = 25 } 

Nell’esempio precedente, si noti che la firma delegata ha un parametro di input implicitamente tipizzato di tipo int e restituisce un int. L’espressione lambda può essere convertita in un delegato di quel tipo perché ha anche un parametro di input (x) e un valore di ritorno che il compilatore può convertire implicitamente in tipo int. (L’inferenza di tipo è discussa in maggior dettaglio nelle sezioni seguenti). Quando il delegato viene invocato usando un parametro di input di 5, restituisce un risultato di 25.

A inizializza un’istanza di un delegato (che può essere chiamato immediatamente). È una variabile di tipo Func .

B specifica la definizione di un delegato (la sua firma). Può essere usato per definire successivamente variabili di tipo convertMethod .