C#如何在for循环前保存变量值快照 循环结束后恢复原值
实现方法
要实现变量在指定代码块内临时修改、退出块后自动恢复原值,且无需手动提前记录原始值,可以通过IDisposable值类型封装临时作用域实现,无额外性能开销,还能保证异常场景下值也能正常还原。
首先定义通用的临时值作用域结构体:
public ref struct TempValueScope<T> { private readonly ref T _targetRef; private readonly T _originalValue; private bool _isDisposed; public TempValueScope(ref T target, T tempValue) { _targetRef = ref target; _originalValue = target; _isDisposed = false; _targetRef = tempValue; } public void Dispose() { if (_isDisposed) return; _targetRef = _originalValue; _isDisposed = true; } }
根据临时值需要生效的范围,调整using声明的位置即可:
- 单次循环迭代内临时改值:作用域声明放在for循环块内部,每次迭代进入时自动赋值为3,单次迭代结束立刻还原
static void Main(string[] args) { Random rnd = new Random(); float myfloat = rnd.Next(1, 50); Console.WriteLine($"循环前初始值:{myfloat}"); for (int i = 0; i <= 2; i++) { // 进入当前迭代块时暂存原值,把myfloat改为3 using var tempScope = new TempValueScope<float>(ref myfloat, 3); Console.WriteLine($"第{i}次循环内取值:{myfloat}"); // 此处编写所有需要使用临时值的逻辑 } // 所有循环迭代结束,值已自动还原为初始随机值 Console.WriteLine($"循环结束后取值:{myfloat}"); Console.ReadLine(); } - 整个for循环执行全程临时改值:作用域声明放在for循环外层,循环全程值为3,循环全部跑完才还原
static void Main(string[] args) { Random rnd = new Random(); float myfloat = rnd.Next(1, 50); Console.WriteLine($"循环前初始值:{myfloat}"); // 进入作用域时暂存原值,把myfloat改为3 using var tempScope = new TempValueScope<float>(ref myfloat, 3); for (int i = 0; i <= 2; i++) { Console.WriteLine($"第{i}次循环内取值:{myfloat}"); // 此处编写循环内逻辑 } // 离开作用域时值自动还原 Console.WriteLine($"循环结束后取值:{myfloat}"); Console.ReadLine(); }
实现说明
- 该结构体为
ref struct,不会产生堆内存分配,性能和手动编码暂存原值、手动还原完全一致 - 初始化作用域时会自动捕获目标变量的引用、暂存原始值,同时赋值为指定的临时值,调用时完全不需要感知原始值是什么
- 基于
using声明的释放机制,不管代码块是正常执行结束还是中途抛出异常,都会自动触发还原逻辑,不会出现值污染 - 该实现为通用方案,任意值类型、引用类型的变量都可以用这个方式做临时值修改
内容的提问来源于stack exchange,提问作者treebeard3
相关产品推荐
相关产品推荐

