提问人:sbi 提问时间:3/29/2011 最后编辑:Communitysbi 更新时间:3/29/2011 访问量:2826
临时更改变量的值
Temporarily change a variable's value
问:
在我目前正在研究的 API 实现中,需要在执行某些任务之前临时重复更改一些变量,并在任务完成后将它们更改回以前的状态。
当前代码如下所示:
var _oldValue = _variable;
_variable = tempValue;
try
{
doIt();
}
finally
{
_variable = oldValue;
}
经常这样做很烦人、丑陋、难以维护,并且将实际算法埋藏在大量混乱之下,这些混乱只是实现工件。
在 C++ 中,我会创建一个类,该类在构造过程中将旧值存储在某个地方,并在其析构函数中恢复它:
{
temp_value tmp(variable_, temp_val);
do_it();
}
当尝试在 C# 中做类似的事情时,我失败了,因为显然 C# 无法在类中存储对其他对象的引用。
那么,我必须在 C# 中做些什么来消除这种混乱呢?
P.S.:随意添加您认为合适的任何其他标签。我什么也想不出来。
答:
为什么不创建一个为你做这件事的方法,然后把一个 Lamda 传递给它呢?
private void SaveGlobalsAndDoSomething(Action doit)
{
var _oldValue = _variable;
_variable = tempValue;
try
{
doit();
}
finally
{
_variable = _oldValue;
}
}
并使用它:
SaveGlobalsAndDoSomething(() => { DoSomething(); });
编辑以回应评论:
有时返回值不是问题。我们不会传递到该方法。我们正在传递到方法。所以你可以很容易地写出:doit
DoSomething
{ DoSomething(); }
int returnValue;
SaveGlobalsAndDoSomething(() => { returnValue = DoSomething(); });
评论
ref
doIt()
void
你正在考虑做各种可怕的、可怕的事情来解决这个问题,这一事实表明你一开始就不应该处于这种情况。如果你的代码依赖于突变,然后取消突变的状态,那么你的设计就很糟糕。解决真正的设计问题,而不是试图想出一个聪明的方法来继续使用糟糕的架构。
当我处于这种情况时,我所做的就是克隆我的状态。假设您正在这样做:
class Frobber
{
State state;
...
void M()
{
...
try
{
oldstate = state;
state = newstate;
this.DoIt();
}
finally
{
state = oldstate;
}
}
相反,请这样做:
class Frobber
{
State state;
...
void M()
{
...
Frobber newFrobber = new Frobber(newstate);
newFrobber.DoIt();
...
与其改变一个变量并将其改回原来,不如创建一个全新的变量。完成新变量后,将其丢弃。旧变量不需要变回,因为它从未改变过。
评论
虽然我同意埃里克·利珀特(Eric Lippert)关于理想解决方案的观点,但在某些情况下,当被迫改变可变状态并执行一些操作时。也就是说,SharePoint 对象模型中有几个此类要求的示例,因此无法重新设计代码来避免它。
下面是可用于临时 cahnge 值并使用语句重新分配的代码。将 用于此类非发布未管理资源的目的是有争议的,因此请您判断这种方法是否适合您:using
using
使用示例:
using(TemporaryChange(true, myValue, v => myValue = v))
{
// code to run while "myValue" is changed to "true"
}
类:
class TemporaryChange<V> : IDisposable
{
private V original;
private Action<V> setValue;
internal TemporaryChange(V value, V currentValue, Action<V> setValue)
{
this.setValue = setValue;
this.original = currentValue;
this.setValue(value);
}
void IDisposable.Dispose()
{
this.setValue(this.original);
}
}
评论
:)
评论
DoItWithRestore()
DoIt()
doIt()
doIt()