为什么C#将匿名方法和闭包实现为实例方法,而不是静态方法?

为什么C#将匿名方法和闭包实现为实例方法,而不是静态方法?,c#,oop,programming-languages,C#,Oop,Programming Languages,由于我不是编程语言方面的专家,我很清楚这可能是一个愚蠢的问题,但我可以告诉你,C#处理匿名方法和闭包的方法是将它们变成匿名嵌套类[1]的实例方法,实例化该类,然后将委托指向这些实例方法 似乎这个匿名类只能实例化一次(或者我错了吗?),那么为什么不让匿名类变成静态的呢 [1] 实际上,似乎有一个类用于闭包,另一个类用于不捕获任何变量的匿名方法,我不完全理解这两个类的原理 我很清楚这可能是个愚蠢的问题 不是 C#通过将匿名方法和闭包生成匿名嵌套类的实例方法,实例化该类,然后将委托指向这些实例方法来

由于我不是编程语言方面的专家,我很清楚这可能是一个愚蠢的问题,但我可以告诉你,C#处理匿名方法和闭包的方法是将它们变成匿名嵌套类[1]的实例方法,实例化该类,然后将委托指向这些实例方法

似乎这个匿名类只能实例化一次(或者我错了吗?),那么为什么不让匿名类变成静态的呢


[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)
返回type
Func
,我们返回
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;
  }
}