Was ist Func<>
und wofür wird es verwendet?Was ist Func, wie und wann wird es verwendet?
Antwort
Func<T>
ist ein vordefinierter Delegattyp für eine Methode, die einen Wert vom Typ T
zurückgibt.
Mit anderen Worten können Sie diesen Typ verwenden, um auf eine Methode zu verweisen, die einen Wert von T
zurückgibt. Z.B.
public static string GetMessage() { return "Hello world"; }
können wie diese
Func<string> f = GetMessage;
Aber es kann auch eine statische ein-Argument-Funktion =) –
@ Ark-Kun Nein, das ist nicht korrekt. Die Definition von 'Func
Nein, ich habe Recht. 'static int OneArgFunc (diese Zeichenfolge i) {return 42; } '' Func
Func<T1,R>
und die anderen vordefinierten generisch Func
Delegierten (Func<T1,T2,R>
, Func<T1,T2,T3,R>
und anderen) sind generische Delegaten verwiesen werden, die den Typen des letzten generischen Parameters zurückzukehren.
Wenn Sie eine Funktion haben, die abhängig von den Parametern unterschiedliche Typen zurückgeben muss, können Sie einen Func
Delegaten verwenden, der den Rückgabetyp angibt.
Betrachten Sie es als Platzhalter. Es kann sehr nützlich sein, wenn Sie Code haben, der einem bestimmten Muster folgt, aber nicht an eine bestimmte Funktionalität gebunden sein muss.
Betrachten Sie beispielsweise die Erweiterungsmethode Enumerable.Select
.
- Die Muster sind: für jedes Element in einer Sequenz, wählen einen Wert aus diesem Elemente (z.B. eine Eigenschaft) und eine neue Folge dieser Werte aus erstellen.
- Der Platzhalter ist: einige Auswahlfunktion, die tatsächlich die Werte für die oben beschriebene Sequenz erhält.
Diese Methode benötigt eine Func<T, TResult>
anstelle einer konkreten Funktion. Dies ermöglicht die Verwendung in beliebigen Kontext, in dem das obige Muster gilt.
Also zum Beispiel sagen, ich habe eine List<Person>
und ich möchte nur den Namen jeder Person in der Liste. Ich kann dies tun:
var names = people.Select(p => p.Name);
Oder sagen, ich will das Alter jeder Person:
var ages = people.Select(p => p.Age);
Sogleich, können Sie sehen, wie ich in der Lage war, die gleichen Code zu nutzen, repräsentieren Muster (mit Select
) mit zwei verschiedenen Funktionen (p => p.Name
und p => p.Age
).
Die Alternative wäre, eine andere Version von Select
jedes Mal zu schreiben, wenn Sie eine Sequenz für eine andere Art von Wert scannen wollten.So um die gleiche Wirkung zu erzielen wie oben, würde ich brauchen:
// Presumably, the code inside these two methods would look almost identical;
// the only difference would be the part that actually selects a value
// based on a Person.
var names = GetPersonNames(people);
var ages = GetPersonAges(people);
mit einem Delegierten als Platzhalter fungieren, ich befreie mich aus mit dem gleichen Muster immer und immer wieder in Fällen wie diesen zu schreiben.
Func<T1, T2, ..., Tn, Tr>
stellt eine Funktion dar, die Argumente (T1, T2, ..., Tn) akzeptiert und Tr zurückgibt.
Zum Beispiel, wenn Sie eine Funktion:
double sqr(double x) { return x * x; }
Sie es als eine Art funktions Variablen speichern könnte:
Func<double, double> f1 = sqr;
Func<double, double> f2 = x => x * x;
Und dann genau verwenden, wie Sie sqr verwenden würden:
f1(2);
Console.WriteLine(f2(f1(4)));
usw.
Denken Sie jedoch daran, dass es sich um einen Delegierten handelt. Weitere Informationen finden Sie in der Dokumentation.
Ausgezeichnete Antwort, aber für die Kompilierung von Stichwort Statisch ist erforderlich – boctulus
Es ist nur ein vordefinierter generischer Delegat. Mit ihr müssen Sie nicht jeden Delegierten deklarieren. Es gibt einen anderen vordefinierten Delegaten, Action<T, T2...>
, der identisch ist, aber void zurückgibt.
Ich finde Func sehr nützlich, wenn ich eine Komponente erstellen, die "on the fly" personalisiert werden muss.
Nehmen Sie dieses sehr einfache Beispiel: eine PrintListToConsole Komponente.
Ein sehr einfaches Objekt, das diese Liste von Objekten auf der Konsole ausgibt. Sie möchten den Entwickler, der es verwendet, die Ausgabe personalisieren lassen.
Zum Beispiel, Sie wollen ihn eine bestimmte Art von Zahlenformat definieren und so weiter.
Ohne Func
Zuerst müssen Sie eine Schnittstelle für eine Klasse erstellen, die die Eingabe nehmen und die Zeichenfolge zu erzeugen, um die Konsole zu drucken.
interface PrindListConsoleRender<T> {
String Render(T input);
}
Dann müssen Sie die Klasse PrintListToConsole erstellen, die die vorherige geschaffene Schnittstelle nehmen und sie über jedes Element der Liste verwenden.
class PrintListToConsole<T> {
private PrindListConsoleRender<T> _renderer;
public void SetRenderer(PrindListConsoleRender<T> r) {
// this is the poin where I can personalize the render mechanism
_renderer = r;
}
public void PrintToConsole(List<T> list) {
foreach (var item in list) {
Console.Write(_renderer.Render(item));
}
}
}
Der Entwickler, die Ihre Komponente verwenden müssen müssen:
1), um die Schnittstelle implementieren
2) passiert die wirkliche Klasse des PrintListToConsole
class myrenderer : PrindListConsoleRender<int> {
public String Render(int input) {
return "Number: " + input;
}
}
class Program {
static void Main(string[] args) {
var list = new List<int> { 1, 2, 3 };
var printer = new PrintListToConsole<int>();
printer.SetRenderer(new myrenderer());
printer.PrintToConsole(list);
string result = Console.ReadLine();
}
}
Func Verwendung es ist viel einfacher
innerhalb der Komponente einen Parameter des Typs Func definieren, dass eine Schnittstelle einer Funktion darstellen, die einen Eingabeparameter des Typs T nehmen und eine Zeichenfolge zurück (die Ausgabe für die Konsole)
class PrintListToConsole<T> {
private Func<T, String> _renderFunc;
public void SetRenderFunc(Func<T, String> r) {
// this is the point where I can set the render mechanism
_renderFunc = r;
}
public void StampaFunc(List<T> list) {
foreach (var item in list) {
Console.Write(_renderFunc(item));
}
}
}
Wenn der Entwickler Verwendung Ihre Komponente es einfach an die Komponente die Implementierung des Func-Typs übergeben, das ist eine Funktion, die die Ausgabe für die Konsole erstellen.
class Program {
static void Main(string[] args) {
var list = new Array[1, 2, 3];
var printer = new PrintListToConsole<int>();
printer.SetRenderFunc((o) => "Number:" + o);
string result = Console.ReadLine();
}
}
Func können Sie eine generische Methode Schnittstelle on the fly definieren. Sie definieren, welcher Typ die Eingänge und welcher Typ der Ausgang ist. Einfach und prägnant.
Vielen Dank für das Posten dieses Marco. Es hat mir wirklich geholfen. Ich habe versucht, Func für eine Weile zu verstehen und auch aktiv in meiner Programmierung zu verwenden. In diesem Beispiel wird der Pfad gelöscht. Ich musste die StampaFunc-Methode hinzufügen, die im ursprünglichen Code weggelassen wurde, wodurch sie nicht angezeigt werden konnte. –
- 1. Was ist std :: Verfall und wann sollte es verwendet werden?
- 2. Was ist GenericParameterHelper und wie wird es verwendet?
- 3. Was ist @JoinColumn und wie wird es in Hibernate verwendet?
- 4. Was ist ViewState in JSF und wie wird es verwendet?
- 5. Was ist @Section-Skripten und was es verwendet wird
- 6. Was ist Dojo und wie man es in asp.net verwendet? und wann sollten wir es benutzen?
- 7. Was ist SS_X_JSESSIONID und wann wird es erstellt?
- 8. Taskdatenlokalität NO_PREF. Wann wird es verwendet?
- 9. Wann wird TWaitResult.wrIOCompletion verwendet?
- 10. Was macht python sys.intern und wann sollte es verwendet werden?
- 11. SignInManager, was ist es und wie, wann zu verwenden?
- 12. Was ist in Rust unwrap und wofür wird es verwendet?
- 13. Wann wird Parallel.For verwendet?
- 14. Wann wird [MTAThread] verwendet?
- 15. Was macht '@reigy' und wann sollte es verwendet werden?
- 16. Wann wird Ertrag verwendet?
- 17. Wann ist es sinnvoll, "class_name obj_name = func()" durch "class_name obj_name {func()}" zu ersetzen?
- 18. Wann wird ein gepufferter Kanal verwendet?
- 19. Wann wird ein Initform verwendet?
- 20. Wann wird React createFragment verwendet?
- 21. Was genau macht `-rdynamic` und wann genau wird es benötigt?
- 22. Tanimoto Partitur und wenn es verwendet wird
- 23. Wann wird die k-fache Kreuzvalidierung verwendet und wann wird der Split-Prozentsatz verwendet?
- 24. Wann wird ein Tag/Label verwendet und wann verzweigt?
- 25. Was bedeutet das SQL # -Symbol und wie wird es verwendet?
- 26. Mercurial - Wann wird update verwendet?
- 27. Java - Was ist <> verwendet und wie heißt es?
- 28. Wann wird Julia's convert() verwendet?
- 29. Was ist kein Bereich Bean und wann es zu verwenden?
- 30. Was ist SAPI und wann würden Sie es verwenden?
Es ist nur eine Abkürzung für Delegaten mit einer bestimmten Signatur. Um die folgenden Antworten vollständig zu verstehen, müssen Sie die Delegierten verstehen ;-) –
In der Antwort von @Oded steht: 'Wenn Sie eine Funktion haben, die abhängig von den Parametern unterschiedliche Typen zurückgeben muss, können Sie einen Func-Delegaten verwenden, Angabe der Rückgabetyp.' – Lijo