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;
}
}