嵌套循环内层方法计算的变量如何高效合规传递到外部使用?
原有方案的问题说明
- 方案1:存在冗余计算,性能损耗大,直接排除
- 方案2:
out参数会降低代码可读性,调用方必须提前声明变量承接,不符合现代C#的编码习惯 - 方案3:静态变量存储会引入全局状态,线程不安全,多次调用
Bar方法会出现值污染的问题,完全不推荐
推荐方案:值元组返回+外层变量承接(C# 7.0及以上版本)
这是目前最简洁、符合C#最佳实践的实现方式,无需引入全局状态,也没有冗余计算,代码可读性高。
修改后的代码如下:
public class Foo { public void Bar() { double baz; // 提前声明变量存储最后一次循环的helper值 int lastHelper1 = 0; int lastHelper2 = 0; var i = 0; while (i < 100) { var j = 0; while (j < 100) { // 接收返回的所有计算结果 var calcResult = DoSomething(i, j); baz = calcResult.Baz; // 每次更新helper值,循环结束后自然保留最后一次的结果 lastHelper1 = calcResult.Helper1; lastHelper2 = calcResult.Helper2; j++; } i++; } // 后续直接使用lastHelper1、lastHelper2即可 } // 修改返回值为值元组,包含所有需要对外暴露的计算结果 private (double Baz, int Helper1, int Helper2) DoSomething(int i, int j) { // 包含大量复杂计算逻辑 var helper1 = i + j; var helper2 = 2*i + j; var baz = helper1 + helper2; return (baz, helper1, helper2); } }
兼容老版本C#的替代方案
如果使用的C#版本不支持值元组,可以自定义轻量结构体承载计算结果,逻辑和值元组方案完全一致:
// 定义只读结构体承载计算结果,避免堆分配开销 private readonly struct CalcResult { public double Baz { get; } public int Helper1 { get; } public int Helper2 { get; } public CalcResult(double baz, int helper1, int helper2) { Baz = baz; Helper1 = helper1; Helper2 = helper2; } } // 修改DoSomething返回值为CalcResult private CalcResult DoSomething(int i, int j) { var helper1 = i + j; var helper2 = 2*i + j; var baz = helper1 + helper2; return new CalcResult(baz, helper1, helper2); }
方案优势
- 无冗余计算,所有结果仅计算一次
- 无全局状态,线程安全,多次调用
Bar方法不会出现值冲突 - 代码意图明确,可读性高,符合现代C#的编码规范
- 没有额外的性能开销,值元组和自定义只读结构体都是值类型,不会产生堆分配
内容的提问来源于stack exchange,提问作者Flippowitsch
相关产品推荐
相关产品推荐

