コンパイルしたら、次の違いがありますか。
delegate { x = 0; }
と
() => { x = 0 }
?
コンパイルしたら、次の違いがありますか。
delegate { x = 0; }
と
() => { x = 0 }
?
短い答え:いいえ。
関連しないかもしれない長い答え:
Func
または などAction
) に割り当てると、匿名のデリゲートが取得されます。編集:式のリンクがいくつかあります。
私はエイミーの答えが好きですが、私は衒学的だと思いました。質問には、「コンパイルしたら」と書かれています。これは、両方の式がコンパイルされたことを示唆しています。1 つをデリゲートに、もう 1 つを式ツリーに変換して、両方をコンパイルするにはどうすればよいでしょうか。これは注意が必要です。匿名メソッドの別の機能を使用する必要があります。ラムダ式によって共有されない唯一のもの。パラメーター リストをまったく指定せずに匿名メソッドを指定すると、void を返し、パラメーターなしで任意のデリゲート型と互換性がありout
ます。この知識があれば、2 つのオーバーロードを構築して、式を完全に明確にし、非常に異なるものにすることができるはずです。
しかし、災害が襲います!少なくとも C# 3.0 では、ブロック本体を含むラムダ式を式に変換することはできません。また、本体に代入を含むラムダ式を変換することもできません (戻り値として使用されている場合でも)。これは、C# 4.0 および .NET 4.0 では変更される可能性があり、式ツリーでより多くの表現が可能になります。つまり、MojoFilter がたまたま示した例では、この 2 つはほぼ常に同じものに変換されます。(詳細は後ほど。)
ただし、本体を少し変更すると、デリゲート パラメーターのトリックを使用できます。
using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
int x = 0;
Foo( () => x );
Foo( delegate { return x; } );
}
static void Foo(Func<int, int> action)
{
Console.WriteLine("I suspect the anonymous method...");
}
static void Foo(Expression<Func<int>> func)
{
Console.WriteLine("I suspect the lambda expression...");
}
}
ちょっと待って!十分に狡猾であれば、式ツリーを使用しなくても 2 つを区別できます。以下の例では、オーバーロード解決ルール (および匿名デリゲート マッチング トリック) を使用しています...
using System;
using System.Linq.Expressions;
public class Base
{
public void Foo(Action action)
{
Console.WriteLine("I suspect the lambda expression...");
}
}
public class Derived : Base
{
public void Foo(Action<int> action)
{
Console.WriteLine("I suspect the anonymous method...");
}
}
class Test
{
static void Main()
{
Derived d = new Derived();
int x = 0;
d.Foo( () => { x = 0; } );
d.Foo( delegate { x = 0; } );
}
}
ああ。子供たちのことを思い出してください。基底クラスから継承されたメソッドをオーバーロードするたびに、小さな子猫が泣き始めます。
上記の 2 つの例では、違いはありません。ゼロです。
表現:
() => { x = 0 }
ステートメント本体を持つ Lambda 式であるため、式ツリーとしてコンパイルできません。実際には、0 の後にセミコロンが必要なため、コンパイルさえしません。
() => { x = 0; } // Lambda statement body
() => x = 0 // Lambda expression body, could be an expression tree.
エイミー B は正しいです。式ツリーを使用する利点があることに注意してください。LINQ to SQL は式ツリーを調べて、それを SQL に変換します。
また、ラムダと式ツリーを使用して、リファクタリング セーフな方法でクラス メンバーの名前を効果的にフレームワークに渡すこともできます。 Moqはその一例です。
違いがあります
例:
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(delegate
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
そして、ラムダ:(エラー) に置き換えます
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(()=>
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});