【问题标题】:Is a static readonly value type lifted in a closure?闭包中是否提升了静态只读值类型?
【发布时间】:2012-07-03 02:51:47
【问题描述】:

如果我有以下情况:

static readonly TimeSpan ExpiredAfter = TimeSpan.FromMilliseconds(60000);

foreach (ModuleInfo info in moduleList.Where(i => DateTime.Now - i.LastPulseTime > ExpiredAfter).ToArray())
    moduleList.Remove(info);

ExpiredAfter 是否被解除或编译器是否知道它可以直接访问它?这样写会不会更有效率:

static readonly TimeSpan ExpiredAfter = TimeSpan.FromMilliseconds(60000);

static bool HasExpired(ModuleInfo i) { return DateTime.Now - i.LastPulseTime > ExpiredAfter; }

foreach (ModuleInfo info in moduleList.Where(HasExpired).ToArray())
    moduleList.Remove(info);

【问题讨论】:

    标签: c# closures


    【解决方案1】:

    不可能捕获静态(或就此而言,任何)字段。

    来自语言规范:

    7.15.5 外部变量 任何局部变量、值参数或参数数组,其范围包括 lambda 表达式或 匿名方法表达式被称为外部变量 匿名函数。在类的实例函数成员中, this value 被认为是一个值参数,是一个外部变量 函数成员中包含的任何匿名函数。

    7.15.5.1 捕获的外部变量 当一个外部变量被匿名函数引用时,就称该外部变量已被匿名函数捕获。

    静态字段绝不是局部变量、值参数或参数数组。

    也就是说,我看到 some strange corner cases 编译器无缘无故地捕获了 this,但这似乎不是其中之一。我使用反编译器验证了在实例和静态封闭方法的情况下,C# 4.0 编译器为 lambda 生成的代码与您的“手动”版本几乎相同...... 除了 编译器似乎正在缓存和重用对生成委托的引用(在静态字段中)用于 lambda 情况。在这种情况下,这可能会违反直觉使 lambda 方式更快(并增加更少的内存压力)比方法组方式在这种情况下(通过封闭方法的多次执行)!不过,您必须以两种方式对其进行基准测试才能确定...

    【讨论】:

    • 我忘记了委托创建,很棒的答案!
    • 我喜欢这是另一种情况,我们应该让编译器进行思考 =)
    • @Tergiver:非常正确。绝对值得进行基准测试以查看影响。
    【解决方案2】:

    ExpiredAfter 是否被解除或编译器是否知道它可以直接访问它?

    最简单的检查方法是编译你的代码,然后在 Reflector 等中反编译。我会期望编译器只生成一个直接访问静态变量的静态方法。

    这样写会不会更有效率:

    再一次,自己测试一下 :) 即使以这种方式编写它更有效率,但这也不会使其必然成为正确的选择。哪个更适合您?这段代码对性能有多关键?是不是已经快够了

    【讨论】:

      猜你喜欢
      • 2012-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多