オブジェクトに対する通常のメソッド呼び出しは、クロージャーとは何の関係もありません。そのメソッド呼び出しをデリゲートとしてパッケージ化する場合にのみ、クロージャがあります!
何が起こっているのかを理解するには、「値型」と「参照型」の概念をよく理解する必要があります。について話すことObject
は、.net では十分に明確ではありません。これObject
は、値の型を含むすべての階層の最下部にあるためです (int
も ですObject
)。クラス インスタンスなどの純粋な参照型でのメソッド呼び出しについて考え始める方がはるかに簡単です。
通常のクラス変数とインスタンス化を取り上げます。
List x; // variable declaration
x = new List(); // instantiation
または、1 行で:
List x = new List();
インスタンスの「本体」は、ヒープと呼ばれるメモリ領域に残ります。作業している はそのx
メモリ領域への参照のみを保持するため、これは と呼ばれreference type
ます。
List
変数を使用してメソッドを呼び出す場合、x
メソッドはどのリストで機能するかを知る必要があります。したがって、このメソッドは、最初のパラメーターであるパラメーターとして、インスタンスの本体への参照を取得するだけthis
です。オブジェクトは常にヒープ上にあり、参照 (またはポインター) のみを渡すため、CLR またはコンパイラーが「オブジェクト」を渡すと言うのは正しくありません。
そのメソッドが同じオブジェクトの別のメソッドを呼び出す必要がある場合、それthis
自体が受け取った最初のパラメーターと同じものを渡すだけです。
通常のメソッド呼び出しは次のようになります。
x.Add(Something); // calls instance method "Add" on "x"
への呼び出しx
の (最初のパラメーター、非表示のパラメーター) として使用する参照を知っていることをコンパイラーが認識した場合。そこに「閉鎖」はありません!this
Add
クロージャーは次のようになります。
List<int> A = new List<int>();
List<int> B = new List<int>();
Action<int> aDelegate; // <-- declare a delegate type variable
// Action<int> is a delegate that returns void and
// takes a single int parameter.
aDelegate = A.Add; // <-- initialize the delegate using an instance method of object A
aDelegate(7); // <- notice the call! No reference to "A" because "A" is already stored in aDelegate
aDelegate = B.Add;
aDelegate(8); // <- notice the call! No reference to "B" because "B" is already stored in aDelegate
デリゲート ( ) を呼び出したときに何が起こるかをよく見るとaDelegate(7)
、コンパイラは何らかの形Add
で object のメソッドを呼び出す必要A
がありますが、それは見えず、隠されています。デリゲートは、オブジェクトへの参照とメソッドA
のアドレスの両方をカプセル化するため、 . 対照的に、そうすると何が起こるかを見てください。今回は object でメソッドが呼び出されますが、 object への参照がデリゲート (クロージャー) 内に埋め込まれているため、それを推測する方法はありません。Add
closure
aDelegate(8)
Add
B
B