コンパイルすると、次のような違いがありますか?
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つはほとんど常に同じものに変換されます。(詳細は1分後に説明します。)
ボディを少し変更する場合は、デリゲートパラメータトリックを使用できます。
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; } );
}
}
痛い。子供を思い出してください。基本クラスから継承されたメソッドをオーバーロードするたびに、小さな子猫が泣き始めます。
delegate { ... }
はないことに注意してください。delegate() { ... }
後者は、パラメーターなしのデリゲート型とのみ互換性があります。
エイミー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));
});
ここにいくつかの基本があります。
これは匿名メソッドです
(string testString) => { Console.WriteLine(testString); };
無名メソッドには名前がないため、これらのメソッドまたは式の両方を割り当てることができるデリゲートが必要です。例えば
delegate void PrintTestString(string testString); // declare a delegate
PrintTestString print = (string testString) => { Console.WriteLine(testString); };
print();
ラムダ式と同じです。通常、それらを使用するにはデリゲートが必要です
s => s.Age > someValue && s.Age < someValue // will return true/false
funcデリゲートを使用して、この式を使用できます。
Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;
bool result = checkStudentAge ( Student Object);