C# 如何覆盖计算值?

C# 如何覆盖计算值?,c#,C#,因此,我有以下代码片段: private Nullable<decimal> _excessWages; public decimal ExcessWages { get { return _excessWages ?? CalculateExcessWages(); } set { if (value != CalculateExcessWages()) _excessWages = v

因此,我有以下代码片段:

private Nullable<decimal> _excessWages;
public decimal ExcessWages
{
    get
    {
        return _excessWages ?? CalculateExcessWages();
    }
    set
    {
        if (value != CalculateExcessWages())
            _excessWages = value;
        else
            _excessWages = null;
    }
}
private Nullable\u超额工资;
公共收入
{
得到
{
返回“超额工资”??计算超额工资();
}
设置
{
如果(值!=CalculateExcessSweels())
_超额工资=价值;
其他的
_超额工资=零;
}
}
所以基本上,我要实现的行为是,如果一个字段留空,或者指定了一个与计算值相等的值,则使用计算值,否则存储指定的值


我有很多字段需要支持这样的重写。这是实现这一目标的最佳方式吗?如果不是,你有什么建议?

在我看来是合理的。我唯一可能做的更改是缓存
CalculateExcessSweels()
,如果这样做很昂贵,那么可以缓存:

private Nullable<decimal> _excessWages;
private Nullable<decimal> _excessWagesCalculated;
public virtual decimal ExcessWages
{
    get
    {
        if (_excessWagesCalculated == null)
            _excessWagesCalculated = CalculateExcessWages();
        return _excessWages ?? _excessWagesCalculated;
    }
    set
    {
        if (_excessWagesCalculated == null)
            _excessWagesCalculated = CalculateExcessWages();
        if (value != _excessWagesCalculated)
            _excessWages = value;
        else
            _excessWages = null;
    }
}
private Nullable\u超额工资;
私人可为空(未经计算);;
公共虚拟十进位超额工资
{
得到
{
如果(_excessWagesCalculated==null)
_excessWagesCalculated=计算超额工资();
返回(超过工资)(超过工资);;
}
设置
{
如果(_excessWagesCalculated==null)
_excessWagesCalculated=计算超额工资();
如果(值!=\u超出计算值)
_超额工资=价值;
其他的
_超额工资=零;
}
}

但是,这比您的代码要多,我认为您正在寻求简化。

您可以为此制作一个类包装器

class OverridableValue<T>
{
    public OverridableValue<T>(Func<T> calculator)
    {
        _calculator = calculator;
    }
    private Nullable<T> _t;
    private Func<T> _calculator;
    public T Get()
    {
        return return _t ?? _calculator();
    }
    public void Set(T value)
    {
        _t = (value != _calculator()) ? value : null;
    }
}
类可重写值
{
公共可重写值(Func计算器)
{
_计算器=计算器;
}
私人可为空(t);
专用函数计算器;
公共部门得不到
{
返回-返回计算器();
}
公共无效集(T值)
{
_t=(值!=\u计算器())?值:空;
}
}
它在语法上不是那么甜美,但至少可以节省一些击键次数

现在您可以这样使用它:

class Foo
{
    OverridableValue<decimal> _excessWages =
            new OverridableValue<decimal>(CalculateExcessWages);
    public decimal ExcessWages
    {
        get { return _excessWages.Get(); }
        set { _excessWages.Set(value); }
    }
    ...
}
class-Foo
{
可覆盖值_超过工资=
新的可覆盖值(CalculateExcessSweels);
公共收入
{
获取{return _excesssweers.get();}
set{u excesssweels.set(value);}
}
...
}

优点是整个逻辑隐藏在类中。

您可以通过定义一个方便的set/get helper方法来实现这一点

private static T GetUtil<T>(ref Nullable<T> value, Func<T> calc) {
  return value ?? calc();
}

private static void SetUtil<T>(ref Nullable<T> value, T newValue, Func<T> calc) {
  if ( newValue != calc() ) {
    value = newValue
  } else {
    value = null;
  }
}

private Nullable<decimal> _excessWages;
public decimal ExcessWages
{
    get { return GetUtil(ref _excessWages, CalculateExcessWages); }
    set { SetUtil(ref _excessWages, value CalculateExcessWages); }
}
private static T GetUtil(ref可为null的值,Func calc){
返回值??计算();
}
私有静态void SetUtil(ref可为null的值、T newValue、Func calc){
如果(newValue!=calc()){
值=新值
}否则{
值=空;
}
}
私人可取消的超额工资;
公共收入
{
获取{return GetUtil(ref_excessWages,CalculateExcessWages);}
set{SetUtil(ref _excessWages,value CalculateExcessWages);}
}

我主要是根据客户的建议来做这件事的。事实证明,您可以使用单个泛型类来抽象它。以下是最终结果:

public class Overridable<T>
{
    private Func<T> _calculate;
    private readonly Func<T, T, bool> _compare;
    protected T _t;

    public Overridable(Func<T> calculate, Func<T, T, bool> compare)
    {
        _calculate = calculate;
        _compare = compare;
    }

    public T Value
    {
        get { return _compare(_t, default(T)) ? _calculate() : _t; }
        set { _t = _compare(value, _calculate()) ? default(T) : value; }
    }
}

我遇到的唯一问题是,
calculateExcessSweels
是一个非静态方法,因此不能在字段初始值设定项中使用它。因为我的类中的所有属性都是非静态的,所以我必须初始化构造函数中的所有支持字段。

您实际询问的是什么;我看到该属性被声明为
virtual
,但从文本中我了解到,您更多的是询问setter内部的代码构造?对此感到抱歉。我删除了虚拟机。这不是我感兴趣的。从最终用户的角度来看,我关心的是“可重写的”。嗯,很有趣。这可能是问题,也可能不是问题。这些可重写属性中有许多是从其他可重写属性计算出来的,这些可重写属性是从其他属性计算出来的,等等。因此,每次访问或更改属性时,属性都会引发一系列计算。当从数据库加载对象、用户重写其中一个属性或用户打印报告或序列化对象时,会发生这种情况。需要考虑的是。并非所有可重写属性都是值类型,因此我需要修改它,以便可以为“\u t”分配任何类型,而不仅仅是可为null的。您基本上需要两个泛型:一个是带有
,其中t:class
,另一个是值类型。
private Overridable<decimal?> _excessWages =
   new Overridable<decimal?>(CalculateExcessWages, (x,y) => x == y);
public virtual decimal? ExcessWages
{
    get
    {
        return _excessWages.Value;
    }
    set
    {
        _excessWages.Value = value;
    }
}