我刚刚花了2天的大部分时间来尝试查找错误,结果发现我不小心使了作为函数输入提供的值发生了变化。
IEnumerable<DataLog>
FilterIIR(
IEnumerable<DataLog> buffer
) {
double notFilter = 1.0 - FilterStrength;
var filteredVal = buffer.FirstOrDefault()?.oilTemp ?? 0.0;
foreach (var item in buffer)
{
filteredVal = (item.oilTemp * notFilter) + (filteredVal * FilterStrength);
/* Mistake here!
item.oilTemp = filteredValue;
yield return item;
*/
// Correct version!
yield return new DataLog()
{
oilTemp = (float)filteredVal,
ambTemp = item.ambTemp,
oilCond = item.oilCond,
logTime = item.logTime
};
}
}
我的首选编程语言通常是C#或C ++,这取决于我认为更适合于要求的语言(这是更适合C#的较大程序的一部分...
现在在C ++中,我将能够通过接受常量迭代器来防止此类错误,因为常量迭代器使您无法在检索值时修改值(尽管我可能需要为返回值构建一个新容器)。我做了一些搜索,找不到任何简单的方法在C#中做到这一点,有人知道吗?
[我当时以为我可以创建一个IReadOnlyEnumerable<T>
类,该类将IEnumerable
作为构造函数,但是后来我意识到,除非在您检索值时对它们进行复制,否则它实际上不会产生任何作用,因为基础值仍然可以修改。
将来有什么方法可以防止此类错误?一些包装器类,或者即使是我要保护的每个函数顶部的一小段代码,也都可以。
目前我能想到的唯一合理的方法是定义我需要的每个类的ReadOnly
版本,然后有一个非只读版本来继承和重载属性并向其中添加函数提供相同类别的可变版本。
如果我对您的理解正确,为实现不变性,您只需要公开DataLog
类中的吸气剂。您可以阅读this回答类的不变性。