ポイント 1 に焦点を当てますが、パフォーマンスの問題全体に 2 セントを与えることから始めます。差が大きくない限り、または使用量が多い場合を除いて、通常、追加されたときにユーザーにとって目に見える違いにならないマイクロ秒については気にしません。非集中的に呼び出されるメソッドを検討する場合にのみ気にしないことを強調します。パフォーマンスに関する特別な考慮事項があるのは、アプリケーション自体を設計する途中です。キャッシング、スレッドの使用、メソッドを呼び出す巧妙な方法 (複数の呼び出しを行うか、1 つだけ呼び出しを行うか)、接続をプールするかどうかなどに関心があります。生のパフォーマンスではなく、スケーラビリティに重点を置いています。1 人のユーザーの場合、1 ナノ秒単位でパフォーマンスが向上するかどうかは気にしません。
そうは言っても、ポイント1についての私の意見は次のとおりです。私は無名メソッドが大好きです。それらは私に大きな柔軟性とコードの優雅さを与えてくれます。匿名メソッドのもう 1 つの優れた機能は、コンテナー メソッドからローカル変数を直接使用できることです (もちろん、IL の観点からではなく、C# の観点から)。多くの場合、大量のコードを省いてくれます。匿名メソッドはいつ使用しますか? 私が必要としているコードが、他の場所では必要とされていない場合があります。2 つの異なる場所で使用する場合、再利用手法としてのコピー アンド ペーストは好きではないので、普通のデリゲートを使用します。したがって、shoosh が答えたように、コードの重複は良くありません。理論的には、匿名は IL のものではなく C# のトリックであるため、パフォーマンスの違いはありません。
匿名メソッドについて私が考えていることのほとんどは、ラムダ式に当てはまります。後者は、匿名メソッドを表すコンパクトな構文として使用できるからです。次の方法を想定しましょう。
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);
}
}
文字列の配列を受け取り、それらのそれぞれに対して、渡されたメソッドを呼び出します。そのメソッドが true を返す場合、"Found..." と表示されます。このメソッドは、次の方法で呼び出すことができます。
string[] names = {"Alice", "Bob", "Charles"};
DoSomethingMethod(names, delegate(string p) { return p == "Alice"; });
ただし、次の方法で呼び出すこともできます。
DoSomethingMethod(names, p => p == "Alice");
ラムダ式を使用する方がはるかに読みやすいため、両者の間に IL の違いはありません。繰り返しになりますが、これらはすべて C# コンパイラのトリック (JIT コンパイラのトリックではない) であるため、パフォーマンスへの影響はありません。匿名メソッドを使いすぎているとは思わなかったのと同様に、匿名メソッドを表すために Lambda 式を使いすぎているとは思いません。もちろん、繰り返されるコードにも同じロジックが適用されます。ラムダを実行せず、通常のデリゲートを使用してください。out または ref 引数の受け渡しなど、匿名メソッドまたはプレーン デリゲートに戻る他の制限があります。
Lambda 式のもう 1 つの優れた点は、まったく同じ構文で匿名メソッドを表す必要がないことです。ラムダ式は、ご想像のとおり、式を表すこともできます。次の例を見てください。
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());
}
}
少し異なる署名に注意してください。2 番目のパラメーターは、デリゲートではなく式を受け取ります。このメソッドを呼び出す方法は次のとおりです。
DoSomethingExpression(names, p => p == "Alice");
これは、ラムダを使用して匿名メソッドを作成するときに行った呼び出しとまったく同じです。ここでの違いは、匿名メソッドを作成するのではなく、式ツリーを作成することです。これらの式ツリーのおかげで、ラムダ式を SQL に変換できます。これは、たとえば、Where、Select などの各句に対してエンジンで何かを実行する代わりに、Linq 2 SQL が行うことです。匿名メソッドを作成する場合でも、式を送信する場合でも、呼び出し構文は同じです。