暂时更改变量的值

时间:2011-03-28 20:44:13

标签: c#

在我正在进行攻击的API实现中,需要在执行某项任务之前暂时重复更改某些变量,并在完成任务之后将其更改回原来的任何变量。

目前的代码如下:

var _oldValue = _variable;
_variable = tempValue;
try
{
  doIt();
}
finally
{
  _variable = oldValue;
}

这么做很烦人,很难看,很难维护,并且在很多杂乱的情况下掩盖了实际的算法,这只是实现工件。

在C ++中,我会创建一个在构造期间在某处存储旧值的类,并在其析构函数中恢复它:

{
  temp_value tmp(variable_, temp_val);
  do_it();
}

尝试在C#I failed中尝试类似的事情,因为显然是C# can't store references to other objects in classes

那么在C#中我需要做些什么才能消除这种混乱?

P.S。:随意添加您认为合适的任何其他标签。我没有提出任何问题。

3 个答案:

答案 0 :(得分:7)

虽然我同意Eric Lippert的理想解决方案,但有些情况下,被迫临时改变可变的状态并执行某些操作。即在SharePoint对象模型中有几个这样的需求示例,因此无法重新设计代码以避免它。

下面是可用于临时修改值并使用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);
    }
}

答案 1 :(得分:6)

为什么不创建一个为您执行此操作的方法,然后将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(); });

答案 2 :(得分:6)

事实上,你正在考虑做一些可怕的,可怕的事情来解决这个问题,这表明你不应该首先处于这种情况。如果您处于代码依赖于变异然后取消突变状态的情况,那么您的设计就会很糟糕。 修复真正的设计问题,而不是试图想出一种聪明的方法来继续使用糟糕的架构。

当我处于这种情况时,我所做的就是克隆我的状态。假设你这样做:

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();
         ...

不是改变变量并改变它,而是创建一个全新的变量。完成后,丢弃新变量。旧变量不需要变回,因为它永远不会改变。