setter中的.NET逻辑和支持字段

时间:2015-09-01 09:12:52

标签: c# .net setter

我有两个属性,当第一个(CalulcatedValue)发生变化时,必须更新后者(FXRate)。

我可以通过CalulcatedValue ReadOnly并从OnPropertyChanged("CalculatedValue") setter调用FXRate来实现此目的。

public double FXRate {
    get { return _fXRate; }
    set {
        Set(_fXRate, value, "FXRate");
        OnPropertyChanged("CaluclatedValue");
    }
}

public float CalculatedValue  
{
    get { return FXRate * SomeOtherValue;}
}

但是我知道CalulcatedValue属性会被调用很多(在几个LINQ查询中使用等)。我正在考虑吸气剂应该很快返回值,并计划为它提供支持。

public double FXRate 
{
    get { return _fXRate;}
    set {
        Set(_fXRate, value, "FXRate");
        CalculatedValue = 0; //how to set CalculatedValue since it's setter is calculating it with its logic, i.e. the value parameter is not needed ?
    }
}
private double _fXRate;

public float CalculatedValue  
{
    get { return _calculatedValue; }
    set {
        __calculatedValue = FXRate * SomeOtherValue); //consider this line takes some effort to be calculated -> instead of SomeOtherValue there might be pretty complex logic here to get the result
        OnPropertyChanged("CalculatedValue");
    }
}
private float _calculatedValue;

现在应该如何设置CalulcatedValue?它不需要传递任何值参数,因为逻辑在setter中。这条线

  

CalulcatedValue = 0

现在发生了愚蠢的事情。

4 个答案:

答案 0 :(得分:2)

如果您需要INotifyPropertyChanged通知,请将其添加到FXRate属性(和/或可能更改CalculatedValue值的任何属性),并在那里进行计算:

private double _fXRate;
private float _calculatedValue;

public double FXRate 
{
  get { return _fXRate;}
  set {
      Set(_fXRate, value, "FXRate");
      _calculatedValue = _fxRate * SomeOtherValue;
      // this will update any control depending on the `CalculatedValue` notification
      OnPropertyChanged("CalculatedValue");
  }
}

public float CalculatedValue  
{
  get { _calculatedValue; }
}

或者,如果您想将计算推迟到第一次阅读(因为您将在实际阅读FxRate之前多次更新CalculatedValue),您可以执行类似的操作:

private double _fXRate;
private float _calculatedValue;
private bool _calculatedValueIsDirty = true;

public double FXRate 
{
  get { return _fXRate;}
  set {
      Set(_fXRate, value, "FXRate");
      _calculatedValueIsDirty = true;
      OnPropertyChanged("CalculatedValue");
  }
}

public float CalculatedValue  
{
  get { 
      if(_calculatedValueIsDirty) {
        _calculatedValue = _fxRate * SomeOtherValue;
        _calculatedValueIsDirty = false;
      }
      return _calculatedValue;
  }
}

CalculatedValue的后续读取将非常快速地返回,除非预先计算的值再次变脏(通过更改FXRate

PS:如果有类似多线程的内容,请在必要时应用锁定: - )

答案 1 :(得分:1)

你根本不需要一个二传手。你需要一个只有吸气剂的财产:

public float CalculatedValue  
{
    get { return FXRate * SomeOtherValue; }
}

如果你正在使用C#6:

public float CalculatedValue => FXRate * SomeOtherValue;

修改

由于计算的价值非常耗时,因此吸气剂可能只有更多的牛肉"因为你有一个扩展的算法,决定是否应该计算属性。

private float calculatedValue;
public float CalculatedValue  
{
    get 
    { 
        if (ShouldRecalculate())
        {
            calculatedValue = DoHeavyCalculation();
        }
        return calculatedValue;
    }
}

答案 2 :(得分:1)

由于CalculatedValue是计算其他属性的结果,因此它不应该有setter。如果您不想因为性能原因而计算出get,请事先计算它:

public double FXRate 
{
   get { return _fXRate;}
   set 
   {
        Set(_fXRate, value, "FXRate");
        CalculateStuff();
   }
}
private double _fXRate;

public float CalculatedValue  
{
    get { return _calculatedValue; }
}

private void CalculateStuff()
{
    // This calculation is private to the class so I see no reason to not use the fields..

    _calculatedValue = _fXRate * SomeOtherValue; //consider this line takes some effort to be calculated -> instead of SomeOtherValue there might be pretty complex logic here to get the result
    OnPropertyChanged("CalculatedValue");
}

private float _calculatedValue;

答案 3 :(得分:0)

好的,所以你的示例计算是一个非常便宜的计算,如果放入缓冲变量,将不会产生显着的改进。为了这个答案,我假设你实际进行的计算要复杂得多,而且价格昂贵。

现在对于属性来说,确保它们在执行时花费相同的时间并且没有很多不相关的副作用总是一件好事。这样你的代码说得很简单。

我认为你已经非常接近你真正想要的了。我怎么能避免隐藏在你房产的所有者中的任何不可读的黑客。此外,我强烈建议在这里使用私人二传手,以避免外面的任何人混淆你的价值观。

我会选择这样的事情:

public double FXRate 
{
    get { return _fXRate;}
    set {
        Set(_fXRate, value, "FXRate");
        CalculatedValue = value * SomeOtherValue;
        /* The calculation is completely done here. Using the value parameter because 
         * it is local and has slightly less overhead then accessing the class variable
         * or the property we are just setting. It is in general a good idea to avoid
         * reading the property in the setter. */
    }
}
private double _fXRate;

public float CalculatedValue  
{
    get { return _calculatedValue; }
    private set {
        Set(_calculatedValue, value, "CalculatedValue");
    }
}
private float _calculatedValue;

通过这种方式,您可以获得一个非常清理的属性模型,并且计算会在实际完成相关更改的地方进行。此时,您还可以检查值是否实际更改,并在不需要时跳过更新昂贵的计算值。