Mi chiedevo se qualcuno potesse spiegare cos'è Func<int, string>
e come viene utilizzato con alcuni chiari esempi.
Risposte:
Hai familiarità con i delegati in generale? Ho una pagina sui delegati e sugli eventi che potrebbero aiutare in caso contrario, anche se è più orientata a spiegare le differenze tra i due.
Func<T, TResult>
è solo un delegato generico: cerca di capire cosa significa in una situazione particolare sostituendo i parametri di tipo ( T
e TResult
) con gli argomenti di tipo corrispondenti ( int
e string
) nella dichiarazione. L'ho anche rinominato per evitare confusione:
string ExpandedFunc(int x)
In altre parole, Func<int, string>
è un delegato che rappresenta una funzione che accetta un int
argomento e restituisce un file string
.
Func<T, TResult>
viene spesso utilizzato in LINQ, sia per le proiezioni che per i predicati (in quest'ultimo caso, TResult
è sempre bool
). Ad esempio, potresti usare a Func<int, string>
per proiettare una sequenza di numeri interi in una sequenza di stringhe. Le espressioni lambda vengono solitamente utilizzate in LINQ per creare i delegati rilevanti:
Func<int, string> projection = x => "Value=" + x;
int[] values = { 3, 7, 10 };
var strings = values.Select(projection);
foreach (string s in strings)
{
Console.WriteLine(s);
}
Risultato:
Value=3
Value=7
Value=10
A Func<int, string>
mangia int e restituisce stringhe. Allora, cosa mangia int e restituisce le stringhe? Cosa ne pensi di questo ...
public string IntAsString( int i )
{
return i.ToString();
}
Lì, ho appena creato una funzione che mangia int e restituisce stringhe. Come lo userei?
var lst = new List<int>() { 1, 2, 3, 4, 5 };
string str = String.Empty;
foreach( int i in lst )
{
str += IntAsString(i);
}
// str will be "12345"
Non molto sexy, lo so, ma questa è la semplice idea su cui si basano molti trucchi. Ora, usiamo invece un Func.
Func<int, string> fnc = IntAsString;
foreach (int i in lst)
{
str += fnc(i);
}
// str will be "1234512345" assuming we have same str as before
Invece di chiamare IntAsString su ogni membro, ho creato un riferimento ad esso chiamato fnc (questi riferimenti ai metodi sono chiamati delegati ) e l' ho usato invece. (Ricorda che fnc mangia int e restituisce stringhe).
Questo esempio non è molto sexy, ma molte delle cose intelligenti che vedrai si basano sulla semplice idea di funzioni, delegati e metodi di estensione .
Uno dei migliori primer su questa roba che ho visto è qui . Ha molti più esempi reali. :)
È un delegato che ne accetta uno int
come parametro e restituisce un valore di tipo string
.
Ecco un esempio del suo utilizzo:
using System;
class Program
{
static void Main()
{
Func<Int32, String> func = bar;
// now I have a delegate which
// I can invoke or pass to other
// methods.
func(1);
}
static String bar(Int32 value)
{
return value.ToString();
}
}
Func<int, string>
accetta un parametro di valore int e restituisce un valore stringa. Ecco un esempio in cui non è necessario un metodo di supporto aggiuntivo.
Func<int, string> GetDogMessage = dogAge =>
{
if (dogAge < 3) return "You have a puppy!";
if (dogAge < 7) return "Strong adult dog!";
return "Age is catching up with the dog!";
};
string youngDogMessage = GetDogMessage(2);
NOTA: L'ultimo tipo di oggetto in Func (cioè "stringa" in questo esempio) è il tipo restituito dalle funzioni (cioè non limitato alle primitive, ma a qualsiasi oggetto). Pertanto, Func<int, bool, float>
accetta parametri di valore int e bool e restituisce un valore float.
Func<int, bool, float> WorthlessFunc = (intValue, boolValue) =>
{
if(intValue > 100 && boolValue) return 100;
return 1;
};
float willReturn1 = WorthlessFunc(21, false);
float willReturn100 = WorthlessFunc(1000, true);
HTH