2016-09-27 12 views
2

ラムダ式の引数を持つ開始スレッドの解が見つかりました。ラムダはどのくらい正確に機能しますか? C#とスレッド

Thread amazonBuy1 = new Thread(() => amazon.Buy("Lego", visa, dhl)); 

私の質問は - ラムダはどのくらい正確に機能していますか? スレッド引数について言えば、デフォルトでは不可能なparamsを持つメソッドをどのように与えることが可能ですか?

ありがとうございます。

+1

@ marc-gravellの答えの短いバージョンは、 "amazon"、 "visa"、および "dhl"変数が実行時にラムダメソッドにアクセスできるように、 "クロージャ"と呼ばれるものを作成することです。クローズを使用する方法を説明するオンラインの良いリソースがたくさんあります。Marcの答えは、C#で実装されている方法の詳細を提供します。 –

答えて

2

Thread amazonBuy1 = new Thread(() => amazon.Buy("Lego", visa, dhl)); 

を...そして私たちはこれを取得する二つの別々の行にそれをリファクタリング:

ThreadStart threadStart =() => amazon.Buy("Lego", visa, dhl); 
Thread amazonBuy1 = new Thread(threadStart); 

のでThreadのコンストラクタは"Lego"を取りません、 visa,のパラメータはすべて、ThreadStartの代理人がかかります。

デリゲートは、メソッドを呼び出すために使用できる変数です。この場合、呼び出されると、代理人はamazon.Buy("Lego", visa, dhl)を実行できます。

これは、スレッドが新しいスレッドの内部からデリゲートを開始して呼び出すことができることを意味します。

コンパイラは、visadhlをデリゲート内にバンドルできるようにすべての魔法を実行します。これは「クロージャー」と呼ばれます。コンパイラは、が2つの変数に対してを閉じるデリゲートを生成します。

0

ラムダ式は無名関数であり、主にLINQで代理人を作成するために使用されます。つまり、アクセス修飾子、戻り値の宣言、および名前のような宣言のないメソッドです。利便性。それはあなたがそれを使用しようとしている同じ場所にメソッドを書くことを可能にする省略表現です。

出典:https://msdn.microsoft.com/en-GB/library/bb397687.aspx

あなたThreadThreadStartParameterizedThreadStartと呼ばれるデリゲートをとります。このようにラムダを使用すると、その場でデリゲートメソッドを作成しています。

+0

が編集されました。そしてそうですか?彼はラムダが何であるか、それが何をしているのか尋ねた。それはまさにそれが彼に伝えるものです。 – ThePerplexedOne

+0

答えは不完全です。ラムダのクロージャが作成されたという事実は記述されていないためです。 –

4

は、私は、コンパイラが何をするかを証明することを許可する:

class __horribleTypeName { 
    public Something amazon; 
    public SomethingElse visa; 
    public AnotherSomething dhl; 
    public void __horribleMethodName() { 
     amazon.Buy("Lego", visa, dhl); 
    } 
} 

... 

var __horribleLocalName = new __horribleTypeName(); 
__horribleLocalName.amazon = ... // etc 
Thread amazonBuy1 = new Thread(__horribleLocalName.__horribleMethodName); 

は意味をなさない?したがって、ラムダの内容はコンパイラ生成メソッドのメソッド本体になります。本体の内部でアクセスするローカルは、コンパイラーが生成したインスタンスのフィールドに移動します。ここで使用されている実際の名前はすべて "unpronouncable"であることに注意してください - C#で表現することはできません - 法的なC#識別子ではありません。上の例は単純な例です - コンテキストがキャプチャされていないときに再利用された静的デリゲートインスタンスに物を持ち上げることを含む、コンパイラがいくつかの状況で行うことができる他の最適化があります。 visaまたはdlhまたはamazonインスタンスフィールドの場合、キャプチャするフィールドはフィールド自体ではなく、thisであることに注意してください。それは次のようになります。注意点として

class __horribleTypeName { 
    public YourType __this; 
    public void __horribleMethodName() { 
     __this.amazon.Buy("Lego", __this.visa, __this.dhl); 
    } 
} 
... 
var __horribleLocalName = new __horribleTypeName(); 
__horribleLocalName.__this = this; 
Thread amazonBuy1 = new Thread(__horribleLocalName.__horribleMethodName); 

:あなたがスレッドに状態を渡したい場合は、ParameterizedThreadStartがあります。私たちはあなたの呼び出し取る場合

+0

この説明からわかりにくいのは、スレッドが開始されたメソッドでもローカル変数が解除されていることです。それ以外の場合は、メソッドの古くなったコピーだけを参照して、後でそれらを変更します。 @Voo確かに; – Voo

+0

;最初の例を使用するには、スレッド開始の直前に 'amazon'の値*を上げないでください。 **元のメソッドの 'amazon'のすべての言及は実際に' __horribleLocalName.amazon'と対話しています。 *変数自体*が再配置されました –

+0

実際には、現在の回答にあるようにこれが失われる可能性があるので、これを強調したかっただけです。 – Voo

関連する問題