无法修改的变量

Lou*_*hys 13 .net c# variables constants readonly

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

Eri*_*ert 24

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

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

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

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

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

详情.

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

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

在声明的局部变量foreach声明也有效readonly-该变量的变化通过循环值每一次,但不能改变它的值.

无法创建只读形式参数,数组元素或指针取消引用.

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


Oli*_*ppi 12

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


cjk*_*cjk 5

您可以使用自定义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;
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

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

  • @Louis,正如Kyle和OneSHOT所说,没有什么可以阻止类改变值,因为它可以直接访问私有变量. (2认同)

Pau*_*eld 5

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

public class SetValueOnce<T>
{
    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;
      }
   }
}
Run Code Online (Sandbox Code Playgroud)