编译器如何正确转换含闭包的C# LeakingClosure代码?
编译器生成的闭包类与方法实现
你遇到的编译错误核心是捕获变量的类型不匹配——Average()返回double,所以闭包类中需要用double类型存储importantStatistic,而非和GetNumbers()返回的int混淆。以下是编译器针对该场景生成的等效代码:
完整模拟代码(含你补充的类)
using System; using System.Collections.Generic; using System.Linq; // 你补充的CheapNumberGenerator类 public class CheapNumberGenerator { public IEnumerable<int> GetNumbers() { for (int i = 1; i <= 10; i++) yield return i; } } // 你补充的ResourceHogFilter类(示例实现) public class ResourceHogFilter { public static IEnumerable<int> Filter(IEnumerable<int> source, double threshold) { foreach (var num in source) if (num > threshold) yield return num; } } public class ClosureDemo { // 原LeakingClosure方法 public static void LeakingClosure() { var results = new CheapNumberGenerator(); double importantStatistic = results.GetNumbers().Average(); var filtered = from n in results.GetNumbers() where n > importantStatistic select n; // 触发查询执行 foreach (var num in filtered) Console.WriteLine(num); } // ------------------------------ // 编译器生成的等效代码(手动模拟) // ------------------------------ // 编译器自动生成的闭包类:用于捕获外部变量 private sealed class COMPILER_Closure { // 字段类型为double,匹配Average()的返回值 public double importantStatistic; // 编译器生成的lambda对应方法 public bool COMPILER_FilterMethod(int n) { // int与double的比较是合法的隐式转换 return n > importantStatistic; } } // 编译器转换后的LeakingClosure方法 public static void COMPILER_LeakingClosure() { COMPILER_Closure closureInstance = new COMPILER_Closure(); var results = new CheapNumberGenerator(); // 将外部变量赋值给闭包类的字段 closureInstance.importantStatistic = results.GetNumbers().Average(); // 将查询表达式转为方法调用,绑定闭包类的方法作为委托 var filtered = results.GetNumbers().Where(new Func<int, bool>(closureInstance.COMPILER_FilterMethod)); // 触发查询执行 foreach (var num in filtered) Console.WriteLine(num); } }
关键说明
- 类型匹配:闭包类中存储
importantStatistic的字段类型为double,完全匹配Average()的返回类型,解决了你遇到的类型不匹配错误。 - 委托绑定:编译器生成的
COMPILER_FilterMethod接收int类型参数,与闭包类的double字段比较——C#允许int和double的隐式比较,因此不会有编译问题。 - 闭包捕获逻辑:外部变量被转移到闭包类的实例字段中,委托通过闭包类实例访问该字段,实现了对变量的捕获。
内容的提问来源于stack exchange,提问作者na_sacc
相关产品推荐
相关产品推荐

