Erklärung von Func

89

Ich habe mich gefragt, ob jemand anhand Func<int, string>einiger klarer Beispiele erklären könnte, was ist und wie es verwendet wird.

zSynopsis
quelle

Antworten:

144

Kennen Sie die Delegierten im Allgemeinen? Ich habe eine Seite über Delegierte und Veranstaltungen, die helfen können, wenn nicht, obwohl sie eher darauf ausgerichtet ist, die Unterschiede zwischen den beiden zu erklären.

Func<T, TResult>ist nur ein generischer Delegat - ermitteln Sie, was dies in einer bestimmten Situation bedeutet, indem Sie die Typparameter ( Tund TResult) durch die entsprechenden Typpargumente ( intund string) in der Deklaration ersetzen . Ich habe es auch umbenannt, um Verwirrung zu vermeiden:

string ExpandedFunc(int x)

Mit anderen Worten, Func<int, string>ist ein Delegat, der eine Funktion darstellt, die ein intArgument aufnimmt und a zurückgibt string.

Func<T, TResult>wird in LINQ häufig sowohl für Projektionen als auch für Prädikate verwendet (im letzteren Fall TResultimmer bool). Sie können beispielsweise a verwenden, Func<int, string>um eine Folge von Ganzzahlen in eine Folge von Zeichenfolgen zu projizieren. Lambda-Ausdrücke werden normalerweise in LINQ verwendet, um die relevanten Delegaten zu erstellen:

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);
}

Ergebnis:

Value=3
Value=7
Value=10
Jon Skeet
quelle
3
"Mit anderen Worten, es ist ein Delegat, der eine Funktion darstellt, die ein int-Argument verwendet und eine Zeichenfolge zurückgibt." Um Verwirrung für andere zu vermeiden, werde ich klarstellen, dass Sie hier von Func <int, string> und nicht von Func <T, TResult> sprechen. Es ist offensichtlich, wenn Sie generische Typen und Delegaten verstehen, aber für diejenigen, die dies nicht tun, kann Func <int, string> an eine Funktion delegieren, die ein int-Argument verwendet und eine Zeichenfolge zurückgibt.
Der echte Napster
Wird klären, wenn ich später wieder auf einem PC bin.
Jon Skeet
2
Ich denke, dies ist tatsächlich nicht so klar wie die Beschreibung und das Beispiel von MSDN. Ich denke auch, dass Sie Informationen darüber hinzufügen sollten, wie der letzte Typparameter der Rückgabetyp ist, um zu verdeutlichen, dass Func <int, int, string> einen String zurückgibt und 2 Ints benötigt. Das hilft zu klären. Nichts persönliches - ich dachte einfach nicht, dass es klar genug war.
TheSoftwareJedi
11
Wirst du also jede Antwort ablehnen, die du für nicht so hilfreich hältst wie dein besonderer Favorit? Ist diese Antwort Ihrer Meinung nach nicht hilfreich ? Denken Sie, dass es vielleicht keine schlechte Idee ist, mehr als eine Sichtweise auf Dinge zu haben?
Jon Skeet
8
@TheSoftwareJedi: Nein, natürlich kein Grund , downvote persönlich zu nehmen - die Tatsache , dass Sie tat downvote aus persönlichen Gründen am Samstag und dann gerade passierte in diesen Thread zu kommen , nachdem wir eine lange Diskussion über E - Mail über angemessenes Verhalten mit waren ist völlig zufällig, nicht wahr?
Jon Skeet
40

A Func<int, string>isst Ints und gibt Strings zurück. Also, was isst Ints und gibt Strings zurück? Wie wäre es damit ...

public string IntAsString( int i )
{
  return i.ToString();
}

Dort habe ich gerade eine Funktion erfunden, die Ints isst und Strings zurückgibt. Wie würde ich es benutzen?

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"

Nicht sehr sexy, ich weiß, aber das ist die einfache Idee, auf der viele Tricks basieren. Verwenden wir stattdessen einen 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

Anstatt IntAsString für jedes Mitglied aufzurufen, habe ich einen Verweis darauf namens fnc erstellt (diese Verweise auf Methoden werden als Delegaten bezeichnet ) und diesen stattdessen verwendet. (Denken Sie daran, dass fnc Ints isst und Strings zurückgibt).

Dieses Beispiel ist nicht sehr sexy, aber eine Menge der cleveren Dinge, die Sie sehen werden, basieren auf der einfachen Idee von Funktionen, Delegaten und Erweiterungsmethoden .

Eine der besten Grundierungen für dieses Zeug, das ich gesehen habe, ist hier . Er hat viel mehr echte Beispiele. :) :)

JP Alioto
quelle
@ Therealnapster Ich mag es auch, aber ich mag deinen Namen mehr.
BKSpurgeon
27

Es ist ein Delegat, der einen intals Parameter verwendet und einen Wert vom Typ zurückgibt string.

Hier ist ein Beispiel für seine Verwendung:

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();
    }
}
Andrew Hare
quelle
3
Danke Andrew. Wollten Sie func (1) anstelle von bar (1) schreiben?
zSynopsis
1

Func<int, string>Akzeptiert einen int-Wert-Parameter und gibt einen Zeichenfolgenwert zurück. Hier ist ein Beispiel, bei dem eine zusätzliche unterstützende Methode nicht erforderlich ist.

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);

HINWEIS: Der letzte Objekttyp in Func (in diesem Beispiel "Zeichenfolge") ist der Rückgabetyp für Funktionen (dh nicht auf Grundelemente, sondern auf ein beliebiges Objekt beschränkt). Daher Func<int, bool, float>akzeptiert Parameter int und bool Wert und gibt einen Float - Wert.

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

jts
quelle