我有一个现有的方法,如下所示: 方法体有超过1000行代码,我不能把它带到这里,只是在方法体中,如果参数的值(我的意思是 index_param )被改变,那么我会得到错误的结果。
public String calculateValue(int index_param) {
//a highly complicated transactional method which returns a String
}
我想确保方法 body 在操作期间不会更改 index_param ,并阻止它更改参数。 你对这种情况更喜欢什么?
答案 0 :(得分:3)
不幸的是,C#没有readonly
的局部变量类似物。
你可以使用Code Contract Assert 需要伪后置条件,虽然我无法找到一种避免额外局部变量的方法,理论上,变异。
public String calculateValue(int index_param) {
int __DO_NOT_MUTATE_ME = index_param;
// a highly complicated transactional method which returns a String
//
Contract.Assert(index_param == __DO_NOT_MUTATE_ME, "No! Don't change the local var");
return result;
}
编辑 - 一些调查结果
代码契约并不像预期的那样适合检测堆栈变量突变。
Contract.Ensures()
必须位于代码块的顶部,Ensures
仅用于推理返回值,而不是本地变量。Contract.Assert
更清晰,因为它可以放在块中的任何位置。如果堆栈变量在运行时发生变异,则抛出它。index_param
(用红色箭头标记)的不良代码行,而是标记警告,我们的合同是荒谬的"考虑添加Contract.Requires(index_param + 1 == index_param);
&#34 ;。嗯......
答案 1 :(得分:3)
参数按值传递。因此,即使您将变量重新分配给方法体中的新值,原始引用也不会发生任何变化。
如果您不希望方法体甚至将变量重新分配给新值,例如java中的final int index_param
或c ++中的const int index_param
,则无等效强>在c#。
答案 2 :(得分:2)
如果你真的是偏执狂,你可以将你的价值包装在一个帮助类中,以确保你的价值不会改变
public static class ReadOnly
{
public static ReadOnly<T> Create<T>(T val) where T : struct
{
return new ReadOnly<T>(val);
}
}
public class ReadOnly<T> where T : struct
{
private readonly T _value;
public ReadOnly(T val)
{
this._value = val;
}
public T Value { get { return this._value; } }
}
public String calculateValue(int index_param) {
//a highly complicated transactional method which returns a String
var read_only_index_param = ReadOnly.Create(index_param);
Console.WriteLine(read_only_index_param.Value);
}
答案 3 :(得分:1)
根据评论,如果是参数,则可以修改。
防止原始值被修改的唯一方法是创建方法的常量值INSIDE,而不是允许它作为参数注入方法。
public String calculateValue() {
const int index_param = 2;
}
第二个选项是添加一个只读私有字段并将index_param参数传递给封闭类&#39;构造函数。这样,您的calculateValue()方法无法更改该字段,但这需要重构。
public class ContainingClass
{
private readonly int _index_param;
public ContainingClass(int index_param)
{
_index_param = index_param;
}
}
这将允许您在calculateValue中使用您的私有字段,并且无法更改它,这将是编译时检查。
请注意,此私人字段仍可通过反射进行更改。也就是说,如果你有任何人不顾一切地破坏你的代码库,你手上就会遇到更大的问题。
答案 4 :(得分:0)
代码合同和/或单元测试是最佳解决方案,但另一种方法是简单地将参数分配给局部变量,并在从方法返回值之前验证参数是否未更改。如果是这样,您将不得不抛出异常,因为您的代码可能存在错误。