为什么C#将匿名方法和闭包实现为实例方法,而不是静态方法?
由于我不是编程语言方面的专家,我很清楚这可能是一个愚蠢的问题,但我可以告诉你,C#处理匿名方法和闭包的方法是将它们变成匿名嵌套类[1]的实例方法,实例化该类,然后将委托指向这些实例方法 似乎这个匿名类只能实例化一次(或者我错了吗?),那么为什么不让匿名类变成静态的呢为什么C#将匿名方法和闭包实现为实例方法,而不是静态方法?,c#,oop,programming-languages,C#,Oop,Programming Languages,由于我不是编程语言方面的专家,我很清楚这可能是一个愚蠢的问题,但我可以告诉你,C#处理匿名方法和闭包的方法是将它们变成匿名嵌套类[1]的实例方法,实例化该类,然后将委托指向这些实例方法 似乎这个匿名类只能实例化一次(或者我错了吗?),那么为什么不让匿名类变成静态的呢 [1] 实际上,似乎有一个类用于闭包,另一个类用于不捕获任何变量的匿名方法,我不完全理解这两个类的原理 我很清楚这可能是个愚蠢的问题 不是 C#通过将匿名方法和闭包生成匿名嵌套类的实例方法,实例化该类,然后将委托指向这些实例方法来
[1] 实际上,似乎有一个类用于闭包,另一个类用于不捕获任何变量的匿名方法,我不完全理解这两个类的原理 我很清楚这可能是个愚蠢的问题 不是 C#通过将匿名方法和闭包生成匿名嵌套类的实例方法,实例化该类,然后将委托指向这些实例方法来处理匿名方法和闭包 C#有时会这样做 似乎这个匿名类只能实例化一次(或者我错了吗?),那么为什么不让匿名类变成静态的呢 在合法的情况下,C#会让你做得更好。它根本不构成闭包类。它使匿名函数成为当前类的静态函数 是的,你错了。如果只分配一次代理就可以成功,C#确实可以成功 (严格说来,这并不完全正确;在一些模糊的情况下,这种优化没有得到实施。但在大多数情况下是这样的。) 实际上,似乎有一个类用于闭包,另一个类用于不捕获任何变量的匿名方法,我不完全理解这两个类的原理 你把你的手指放在了你没有充分理解的东西上 让我们看一些例子:
class C1
{
Func<int, int, int> M()
{
return (x, y) => x + y;
}
}
现在,学员不仅需要知道传入的this.x
的值,还需要知道传入的y
的值。必须存储在某个地方,所以我们将其存储在字段中。但它不能是C3的字段,因为我们如何告诉b
使用123,告诉g
使用789作为y
的值?它们具有相同的C3
实例,但是y
有两个不同的值
class C3
{
class Locals
{
public C3 __this;
public int __y;
public int Anonymous() { return this.__this.x + this.__y; }
}
Func<int> M(int y)
{
var locals = new Locals();
locals.__this = this;
locals.__y = y;
return locals.Anonymous;
}
}
C3类
{
阶级本地人
{
公共C3-这一点;
公共国际;
public int Anonymous(){返回this.\uu this.x+this.\uuu y;}
}
函数M(整数y)
{
var locals=新的局部变量();
本地人;
本地人;
返回本地人。匿名;
}
}
练习:现在假设我们有C4
和一个通用方法M
,其中lambda在类型T和U的变量上闭合。描述现在必须发生的codegen
练习:现在假设我们有M返回一个委托元组,一个是()=>x+y
,另一个是(int-newY)=>{y=newY;}
。描述两位学员的代码
练习:现在假设M(int y)
返回typeFunc
,我们返回a=>b=>this.x+y+z+a+b
。描述代码
练习:假设一个lambda在这个
上关闭,一个本地执行基本
非虚拟调用。出于安全原因,从虚拟方法的类型层次结构中不直接包含的类型中的代码执行base
调用是非法的。描述在这种情况下如何生成可验证代码
锻炼:把它们放在一起。如何使用getter和setter lambda对所有局部变量执行多个嵌套lambda的codegen,这些局部变量由类和方法范围内的泛型类型参数化,并执行
base
调用?因为这是我们必须解决的问题 @HansPassant:我很困惑——你是说对实例方法的委托调用比对静态方法的委托调用快,这就是让隐藏类具有实例字段而不是静态字段的基本原理吗?Hans的观点是没有“静态类”。静态类只是(1)抽象的,(2)密封的,(3)只有静态方法的类。从CLR的角度来看,它只是一个普通的类。优化是(1)我们可以缓存委托并重用它吗?(2)我们可以避免分配闭包类吗?请参阅我的答案,了解哪些情况下可以进行这些优化。
class C2
{
static int counter = 0;
int x = counter++;
Func<int, int> M()
{
return y => this.x + y;
}
}
class C2
{
static int counter = 0;
int x = counter++;
int Anonymous(int y) { return this.x + y; }
Func<int, int> M()
{
return this.Anonymous;
}
}
class C3
{
static int counter = 0;
int x = counter++;
Func<int> M(int y)
{
return () => x + y;
}
}
var a = new C3();
var b = a.M(123);
var c = b(); // 123 + 0
var d = new C3();
var e = d.M(456);
var f = e(); // 456 + 1
var g = a.M(789);
var h = g(); // 789 + 0
class C3
{
class Locals
{
public C3 __this;
public int __y;
public int Anonymous() { return this.__this.x + this.__y; }
}
Func<int> M(int y)
{
var locals = new Locals();
locals.__this = this;
locals.__y = y;
return locals.Anonymous;
}
}