【发布时间】:2020-07-14 09:33:11
【问题描述】:
我刚刚花了 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 作为构造函数,但后来我意识到,除非它在您检索它们时复制值,否则它实际上不会有任何效果,因为基础价值仍然可以修改。
我有什么办法可以防止将来出现此类错误?一些包装类,或者即使它是我要保护的每个函数顶部的一个小代码 sn-p,真的什么都可以。
目前我能想到的唯一可行的方法是为我需要的每个类定义一个ReadOnly 版本,然后有一个非只读版本来继承和重载属性并添加函数提供同一类的可变版本。
【问题讨论】:
-
您是否考虑过让
DataLog成为一个不可变的类。 -
感谢@Salah 的格式检查,虽然
realised不是一个错误XD -
@juharr 我在上一段中提到过,除非这不是你的意思?
-
我是说拥抱不可变并且不要为类的可变版本而烦恼。
-
@TheBeardedQuack 不客气。你是对的,这不是一个错误,但拼写检查器建议改用“realized”,这就是我改变它的原因:)
标签: c# function parameters immutability