2015-09-01 54 views
3

我有兩個屬性,其中第一個(CalulcatedValue)必須在第一個(FXRate)更改時更新。設置員和後臺字段中的.NET邏輯

我可以通過製作CalulcatedValue ReadOnly,並且只需從FXRate setter調用OnPropertyChanged("CalculatedValue")

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

是在愚蠢的事現在會發生。

+3

讓一個不使用'value'的setter是一種典型的代碼味道。只是沒有一個。 – Jcl

回答

1

你根本不需要一個setter。如果您使用C#6

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

:你只需要一個getter屬性

public float CalculatedValue => FXRate * SomeOtherValue; 

編輯:

由於計算的值是耗時的,也許是吸氣只應有更多的「牛肉」,因爲你有一個擴展的算法,決定是否應該計算財產。

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

這正是OP想要避免的(因爲計算可能需要一些時間)。 – M4N

+0

我編輯了原來的帖子來澄清。這正是我想避免的,因爲計算量很大。 – Nuts

+0

如果計算耗時且他想要快速返回,那麼這應該不是一個屬性。 –

1

由於CalculatedValue是計算其他屬性的結果,因此它不應該有setter。如果你不想來計算獲得性能的原因,預先計算出它像這樣:

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; 
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將恢復得很快,除非precaculated值再次變髒(通過改變FXRate

PS:如果有任何類似的多線程應用鎖在必要:-)

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; 

這種方式你的屬性非常清理模型以及發生在計算,其中相關的變化實際上是完成的。此時,您還可以檢查該值是否實際更改,並在不需要的情況下跳過更新昂貴的計算值。