我有以下“计算”课程。
public class Foo
{
private int? _sum = 0;
public int Sum
{
get
{
if (_sum == null)
_sum = 1 + 1; //simple code to show "some" calculation happens...
return _sum.GetValueOrDefault();
}
}
}
在这个示例中,只有1个Field / Member,但在我的真实课程中,大约有50个成员,所有成员看起来都相似,只是进行了不同的值计算。
在课堂上我也有Recalc方法。
这个Recalc方法做了4件事
我不确定这是存储旧值并使用新值检查更改的最佳方法。
我目前的实施是:
public string GetValuesKey()
{
//again this method only handles the 1 Member and not all 50 in real app its string.Format("{0}|{1}|{2}|...{49}|{50}|", ....);
return string.Format("{0}|", this.Sum);
}
public void Recalc()
{
var oldValues = GetValuesKey();
//set all fields to null
//call the getters
var newValues = GetValuesKey();
if (oldValues != newValues)
{
//something changed...
}
}
但是这个代码有一个内存/性能问题,因为我正在用结构(十进制)写入引用类型(字符串)。
我有点想阻止为所有成员做50个额外的字段(如_oldSum)。 我只需要在Recalc程序中检查是否有任何成员发生了变化。
以防万一,我无法执行以下代码。
public void Recalc()
{
var changes = false;
var oldValue = this.Sum;
_sum = null;
var newValue = this.Sum;
if (oldValue != newValue)
changes = true;
//check next member
oldValue = this.Sum2;
_sum2 = null;
newValue = this.Sum2;
if (oldValue != newValue)
changes = true;
//check next member and so on...
}
因为我需要首先将所有字段设置为null,并且只有在所有字段都设置为null之后我才能执行getter,因为如果Sum Member会聚合其他两个成员,那么成员依赖于彼此。他们还没有被设置为null,他们仍然会有旧值。
因此,我需要一种方法来存储代表所有值的内容,然后再将字段设置为null,并在调用成员的getter之后检查更改。
欢迎任何帮助。
修改
这是代码,我写的是测试性能/内存: http://pastebin.com/3WiNJHyS
答案 0 :(得分:1)
如果您不想自己编写所有50个_oldValue
字段,唯一的选择是使用Reflection,这意味着一些装箱/拆箱,因此性能不是最好的。
无论如何,在以下实现中,我假设在Foo
类中,计算中涉及的成员都是唯一属于decimal?
类型属性的成员。
否则,我们需要一个更复杂的解决方案,在所涉及的每个字段/属性上都有BindingFlags
和/或Attribute
,依此类推。
public void Recalc()
{
var propertyInfos = GetType()
.GetProperties()
.Where(pInfo => pInfo.PropertyType.IsValueType);
var fieldInfos = GetType()
.GetFields()
.Where(fInfo => fInfo.FieldType.IsValueType);
//create a dictionary with all the old values
//obtained from the backing fields.
var oldValueDictionary = fieldInfos.ToDictionary(
fInfo => fInfo.Name,
fInfo => (decimal?)fInfo.GetValue(this));
//set all properties to null
foreach (var pInfo in propertyInfos)
pInfo.SetValue(this, null);
//call all the getters to calculate the new values
foreach (var pInfo in propertyInfos)
pInfo.GetValue(this);
//compare new field values with the old ones stored in the dictionary;
//if only one different is found, the if is entered.
if (fieldInfos.Any(fInfo =>
(decimal?)fInfo.GetValue(this) != oldValueDictionary[fInfo.Name]))
{
//do stuffs
}
}
最后请注意,您的班级配置非常奇怪。您确定在吸气剂中设置所有计算是最佳选择吗?也许你应该重新考虑一下你的设计。一个任务是检索属性值(一个getter),另一个任务是计算某些东西(从支持字段中存储的某个值开始)...
答案 1 :(得分:1)
不是将字符串中的所有值组合在一起并且在字符串构造上有一些特性 - 将所有值放在数组(decimal
)中,然后将所有字段设置为null,进行计算并比较旧数组和新的价值观。