0

我想我了解闭包是如何在 C# 和 .NET 中实现的。当 CLR 检测到一个函数将被传递到其作用域之外并作用于一个自由变量时,它会将函数和该变量打包到一个自定义类中。

那么这与object调用它自己的函数之一时发生的情况有什么不同呢?本身作为第object一个变量传递给函数,因此如果函数需要对象的任何其他函数、属性或字段,它可以访问它们。

我想我在这里遗漏了一些东西,并且想对这两种情况下发生的事情进行某种解释:闭包,以及对象调用其自己的方法之一的情况。

4

1 回答 1

1

对象上的普通方法调用与闭包无关;如果您将该方法调用打包为委托,您只有一个闭包!

为了理解发生了什么,您需要很好地掌握“值类型”和“引用类型”的概念。在 .net 中谈论Object不够明确,因为Object它位于所有内容的层次结构的底部,包括值类型(int也是Object)。开始考虑对纯引用类型(如类实例)的方法调用要容易得多。

拿你的普通类变量和实例化:

List x; // variable declaration
x = new List(); // instantiation

或者,在一行中:

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)) 时发生的情况,编译器不知何故需要调用Addobject 上的方法A,但您看不到,它被隐藏了。委托封装了对对象的引用A和方法的地址,Add这就是为什么它被称为closure. 作为对比,看看你这样做时会发生什么aDelegate(8);这个 time 方法Add是在 object 上调用的B,但无法猜测,因为对 object 的引用再次B被埋在委托(闭包)中。

于 2013-10-06T05:57:02.687 回答