无法修改的变量

C#是否允许无法修改的变量? 它就像一个const ,但不必在声明时为它赋值,该变量没有任何默认值,但只能在运行时赋值一次(编辑:可能不是从构造函数)。 或者这不可能吗?

您可以创建自己的通用类来提供此function,但这可能有点过分。

 public class SetValueOnce { public bool _set; private T _value; public SetValueOnce() { _value = default(T); _set = false; } public SetValueOnce(T value) { _value = value; _set = true; } public T Value { get { if(!_set) throw new Exception("Value has not been set yet!"); return _value; { set { if(_set) throw new Exception("Value already set!"); _value = value; _set = true; } } } 

是的,在C#中有几种方法可以做到这一点。

首先,什么是“变量”? 变量是存储位置。 局部变量,方法的forms参数(以及索引器,构造函数等),静态和实例字段,数组元素和指针解引用都是变量。

某些变量可以声明为“只读”。 “readonly”变量只能通过声明中的初始化程序或构造函数更改一次。 只有字段声明才能读取; C#不支持用户声明的只读本地。

对只读变量有一些限制,有助于确保C#的正常操作不会引入突变。 这可能会导致一些意想不到的结果! 看到

http://ericlippert.com/2008/05/14/mutating-readonly-structs/

详情。

一些当地人也是有效的。 例如,当你说using(Stream s = whatever)然后在使用的嵌入语句中你不能改变s的值。 这种限制的原因是为了防止您创建要处置的资源的错误,然后在处置变量s的内容时处置不同的资源。 最好是一样的。

(不幸的是,C#中存在错误,涉及处理资源是结构类型的情况,结构有一个方法可以改变结构,而局部变量是或者不是匿名函数或迭代器块的封闭本地;由于情景模糊不清,修复可能会破坏,我们还没有采取任何措施,等待进一步分析。)

foreach语句中声明的局部变量也是有效的readonly – 该变量每次循环都会更改值,但不允许更改其值。

无法生成只读forms参数,数组元素或指针取消引用。

有多种方法可以“中断”只读限制并写入一个应该只读的变量。 如果您有足够的权限,可以使用Reflection或不安全的代码来破解CLR的任何安全限制。 如果你这样做会伤害,不要这样做; 有了这些权力,就有责任知道你在做什么,做得对。

您可以声明一个只能在构造函数中设置的readonly变量,或者直接通过其声明来设置。

您可以使用自定义setter滚动自己(但不要使用Object除非必须,请选择正确的类):

 private Object myObj = null; private Boolean myObjSet = false; public Object MyObj { get { return this.myObj; } set { if (this.myObjSet) throw new InvalidOperationException("This value is read only"); this.myObj = value; this.myObjSet = true; } } 

编辑:

这并不会阻止类内部更改私有字段。

当然。 您可以使用readonly

即: public readonly int z;

这只能在构造函数中修改。

来自MSDN :

您只能在以下上下文中为只读字段分配值:

在声明中初始化变量时,例如:

  • public readonly int y = 5;

  • 对于实例字段,在包含字段声明的类的实例构造函数中,或者对于包含字段声明的类的静态构造函数中的静态字段。 这些也是将readonly字段作为outref参数传递有效的唯一上下文。

但是,如果您想要创建只能在创建它的类中更改的属性,则可以使用以下命令:

 public string SetInClass { get; private set; } 

这允许在类中进行更改,但不能从类外部更改变量。

由于@Ivan最近提出了一个类似的问题 ,让我建议另一种在代码中的任何地方实现属性的方法,当然,更确切地说,在通用构造函数的支持下。

 public class Immutable { public T Val { get; private set; } public Immutable(T t) { Val = t; } } 

用法是

 var immutableInt1 = new Immutable(3); // you can set only once immutableInt1.Val = 5; // compile error here: set inaccessible Console.WriteLine("value: " + immutableInt1.Val); 

关键是,如果您尝试设置新值,现在会出现编译错误。

除此之外,我相信如果你想遵循这个范例,你最好使用像F#这样的函数式语言而不是C#。

您可以定义一个只能在对象构造函数中设置其值的只读变量。

在这里阅读: http : //msdn.microsoft.com/en-us/library/acdd6hb7%28v=VS.100%29.aspx

可以标记一个readonly字段,这将要求您在声明点或构造函数中设置一个值,然后将阻止它在构造后重新分配。

但是,虽然引用是只读的,但对象也不一定如此。 为了防止对象本身被修改,你必须使类型成为不可变的,或者提供一个只暴露底层类型的非破坏性方法和属性的包装类。

如果要在构造包含它的对象之后在运行时分配变量,则可以使用具有setter方法的自定义属性,该方法只能修改一次。 即。

 private myVariable = null; public object MyVariable { get { return myVariable; } set { if(myVariable == null ) myVariable = value; }