Auch wenn ich mich auf den ersten Punkt konzentrieren werde, möchte ich zunächst meine Meinung zum Thema Leistung äußern. Solange die Unterschiede nicht groß sind oder die Nutzung intensiv ist, kümmere ich mich in der Regel nicht um Mikrosekunden, die in der Summe für den Benutzer keinen sichtbaren Unterschied ausmachen. Ich betone, dass es mir nur dann egal ist, wenn es sich um nicht-intensive aufgerufene Methoden handelt. Wo ich besondere Leistungsüberlegungen anstelle, ist die Art und Weise, wie ich die Anwendung selbst entwerfe. Ich kümmere mich um die Zwischenspeicherung, um die Verwendung von Threads, um clevere Methoden zum Aufrufen von Methoden (ob mehrere Aufrufe oder nur ein Aufruf), ob Verbindungen gepoolt werden sollen oder nicht, usw., usw. In der Tat konzentriere ich mich normalerweise nicht auf die reine Leistung, sondern auf die Skalierbarkeit. Es ist mir egal, ob es für einen einzelnen Benutzer um ein winziges Stückchen einer Nanosekunde besser läuft, aber ich lege großen Wert darauf, dass ich das System mit einer großen Anzahl gleichzeitiger Benutzer belasten kann, ohne dass ich die Auswirkungen bemerke.
Dies vorausgeschickt, möchte ich meine Meinung zu Punkt 1 darlegen. Ich liebe anonyme Methoden. Sie bieten mir große Flexibilität und einen eleganten Code. Ein weiteres großartiges Merkmal anonymer Methoden ist, dass sie es mir ermöglichen, lokale Variablen direkt aus der Containermethode zu verwenden (aus der C#-Perspektive, nicht aus der IL-Perspektive, natürlich). Sie ersparen mir oft eine Menge Code. Wann verwende ich anonyme Methoden? Jedes Mal, wenn das Stück Code, das ich benötige, nicht an anderer Stelle gebraucht wird. Wenn es an zwei verschiedenen Stellen verwendet wird, mag ich Copy-Paste als Wiederverwendungstechnik nicht, also verwende ich einen einfachen alten Delegaten. Wie shoosh schon sagte, ist es nicht gut, Code zu duplizieren. Theoretisch gibt es keine Leistungsunterschiede, da Anonyme C# Tricks sind, nicht IL Zeug.
Das meiste, was ich über anonyme Methoden denke, gilt auch für Lambda-Ausdrücke, da letztere als kompakte Syntax zur Darstellung anonymer Methoden verwendet werden können. Nehmen wir die folgende Methode an:
public static void DoSomethingMethod(string[] names, Func<string, bool> myExpression)
{
Console.WriteLine("Lambda used to represent an anonymous method");
foreach (var item in names)
{
if (myExpression(item))
Console.WriteLine("Found {0}", item);
}
}
Sie erhält ein Array von Strings und ruft für jeden dieser Strings die ihr übergebene Methode auf. Wenn diese Methode "true" zurückgibt, steht dort "Found...". Sie können diese Methode auf folgende Weise aufrufen:
string[] names = {"Alice", "Bob", "Charles"};
DoSomethingMethod(names, delegate(string p) { return p == "Alice"; });
Sie können es aber auch folgendermaßen nennen:
DoSomethingMethod(names, p => p == "Alice");
Es gibt keinen Unterschied in der IL zwischen den beiden, wobei diejenige, die den Lambda-Ausdruck verwendet, viel besser lesbar ist. Auch hier gibt es keine Auswirkungen auf die Leistung, da dies alles C#-Compiler-Tricks sind (keine JIT-Compiler-Tricks). Genauso wenig wie ich das Gefühl hatte, dass wir anonyme Methoden übermäßig verwenden, glaube ich, dass wir Lambda-Ausdrücke zur Darstellung anonymer Methoden übermäßig verwenden. Die gleiche Logik gilt natürlich auch für wiederholten Code: Verwenden Sie keine Lambdas, sondern reguläre Delegierte. Es gibt noch andere Einschränkungen, die Sie zu anonymen Methoden oder einfachen Delegaten zurückführen, wie out oder ref argument passing.
Ein weiterer Vorteil von Lambda-Ausdrücken ist, dass die gleiche Syntax nicht für eine anonyme Methode verwendet werden muss. Lambda-Ausdrücke können auch... Sie ahnen es, Ausdrücke darstellen. Nehmen Sie das folgende Beispiel:
public static void DoSomethingExpression(string[] names, System.Linq.Expressions.Expression<Func<string, bool>> myExpression)
{
Console.WriteLine("Lambda used to represent an expression");
BinaryExpression bExpr = myExpression.Body as BinaryExpression;
if (bExpr == null)
return;
Console.WriteLine("It is a binary expression");
Console.WriteLine("The node type is {0}", bExpr.NodeType.ToString());
Console.WriteLine("The left side is {0}", bExpr.Left.NodeType.ToString());
Console.WriteLine("The right side is {0}", bExpr.Right.NodeType.ToString());
if (bExpr.Right.NodeType == ExpressionType.Constant)
{
ConstantExpression right = (ConstantExpression)bExpr.Right;
Console.WriteLine("The value of the right side is {0}", right.Value.ToString());
}
}
Beachten Sie die leicht veränderte Unterschrift. Der zweite Parameter empfängt einen Ausdruck und nicht einen Delegaten. Der Aufruf dieser Methode wäre wie folgt:
DoSomethingExpression(names, p => p == "Alice");
Das ist genau derselbe Aufruf, den wir bei der Erstellung einer anonymen Methode mit einem Lambda gemacht haben. Der Unterschied ist, dass wir hier keine anonyme Methode, sondern einen Ausdrucksbaum erstellen. Dank dieser Ausdrucksbäume können wir dann Lambda-Ausdrücke in SQL übersetzen, was zum Beispiel Linq 2 SQL macht, anstatt für jede Klausel wie Where, Select usw. etwas in der Engine auszuführen. Das Schöne daran ist, dass die Aufrufsyntax dieselbe ist, egal ob man eine anonyme Methode erstellt oder einen Ausdruck sendet.
2 Stimmen
Ich empfehle Ihnen, www.lambdaexpression.net zu besuchen.
6 Stimmen
@Delashmate-Domain wird jetzt von Spammern übernommen