Spiegazione di Func


89

Mi chiedevo se qualcuno potesse spiegare cos'è Func<int, string>e come viene utilizzato con alcuni chiari esempi.

Risposte:


145

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 ( Te TResult) con gli argomenti di tipo corrispondenti ( inte 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 intargomento 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

3
"In altre parole, è un delegato che rappresenta una funzione che accetta un argomento int e restituisce una stringa." Solo per evitare confusione agli altri, chiarirò che stai parlando di Func <int, string> qui e non di Func <T, TResult>. È ovvio se si comprendono tipi e delegati generici, ma per coloro che non lo sono è Func <int, string> che può delegare a una funzione che accetta un argomento int e restituisce una stringa.
Il vero napster

Chiarirà quando torno su un PC più tardi.
Jon Skeet

2
Penso che questo in realtà non sia così chiaro come la descrizione e l'esempio di MSDN. Penso anche che dovresti aggiungere informazioni su come l'ultimo parametro di tipo è il tipo restituito, chiarendo che Func <int, int, string> restituisce stringa e accetta 2 int. Questo aiuta a chiarire. Niente di personale - semplicemente non pensavo fosse abbastanza chiaro.
TheSoftwareJedi

11
Quindi sottovaluterai ogni risposta che ritieni non utile come la tua preferita in particolare? Questa risposta è attivamente inutile , pensi? Pensi che forse avere più di un modo di vedere le cose potrebbe non essere una cattiva idea?
Jon Skeet

8
@TheSoftwareJedi: No, naturalmente, alcun motivo per prendere il vostro downvote personalmente - il fatto che si fatto downvote per motivi personali il Sabato e poi appena accaduto a venire in questa discussione dopo che abbiamo avuto una lunga discussione su e-mail su comportamento appropriato è del tutto casuale, non è vero?
Jon Skeet

40

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. :)


@ Therealnapster piace anche a me ma mi piace di più il tuo nome.
BKSpurgeon

27

È un delegato che ne accetta uno intcome 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();
    }
}

3
Grazie Andrew. Volevi scrivere func (1) invece di bar (1)?
zSynopsis

1

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

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.