无法修改的变量

时间:2022-01-10 23:08:18

Does C# allow a variable that can't be modified? It's like a const, but instead of having to assign it a value at declaration, the variable does not have any default value, but can only be assigned a value once at runtime (EDIT: and possibly not from constructor). or is this not possible?

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

9 个解决方案

#1


5  

You could create your own generic class that provided this functionality, but that might be overkill.

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

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;
      }
   }
}

#2


24  

Yes, there are several ways to do that in C#.

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

First off, what is a "variable"? A variable is a storage location. Local variables, formal parameters of methods (and indexers, constructors and so on), static and instance fields, array elements and pointer dereferences are all variables.

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

Some variables can be declared as "readonly". A "readonly" variable can only be changed once, either by an initializer in the declaration, or in a constructor. Only fields declarations can be readonly; C# does not support user-declared readonly locals.

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

There are certain restrictions on readonly variables that help ensure that the normal operation of C# does not introduce a mutation. This can lead to some unexpected results! See

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

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

for details.

Some locals are effectively readonly as well. For example, when you say using(Stream s = whatever) then inside the embedded statement of the using you cannot change the value of s. The reason for this restriction is to prevent the bug whereby you create a resource that is to be disposed, and then dispose of a different resource when the contents of variable s are disposed. It had better be the same.

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

(Unfortunately there are bugs in C# involving the situation where the disposed resource is a struct type, the struct has a method which mutates the struct, and the local variable is or is not a closed-over local of an anonymous function or iterator block; since the scenarios are obscure and the fix would be potentially breaking we haven't done anything about it yet, pending further analysis.)

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

The local variable declared in a foreach statement is also effectively readonly -- that variable changes value every time through the loop, but you are not allowed to change its value.

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

There is no way to make a readonly formal parameter, array element or pointer dereference.

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

There are various ways to "break" the readonly restriction and write to a variable that is supposed to be read only. You can use Reflection or unsafe code to break pretty much any safety restriction of the CLR if you have sufficient privilege to do so. If it hurts when you do that, don't do that; with those powers comes the responsibility to know what you're doing and do it right.

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

#3


12  

You can declare a readonly variable which can be set only in the constructor or directly through its declaration.

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

#4


5  

You can roll your own using a custom setter (but don't use Object unless you have to, choose the correct class):

您可以使用自定义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;
    }
}

EDIT:

This doesn't stop the private field being changed by the class internals.

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

#5


4  

Sure. You can use readonly:

当然。您可以使用readonly:

I.e.: public readonly int z;

即:public readonly int z;

This can only be modified from within the constructor.

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

From MSDN:

You can assign a value to a readonly field only in the following contexts:

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

When the variable is initialized in the declaration, for example:

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

  • public readonly int y = 5;

    public readonly int y = 5;

  • For an instance field, in the instance constructors of the class that contains the field declaration, or for a static field, in the static constructor of the class that contains the field declaration. These are also the only contexts in which it is valid to pass a readonly field as an out or ref parameter.

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

If however you are wanting to make a property that can only be altered within the class that created it, you can use the following:

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

public string SetInClass
{
   get;
   private set;
}

This allows changes to be made within the class, but the variable cannot be altered from outside the class.

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

#6


2  

Since a similar question has been recently asked by @Ivan, let me suggest yet another method to instanciate a property at any place in the code, of course, more exactly, with the support of a generic constructor.

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

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

Usage would be

用法是

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

The point is that now you get a compile error if you try to set a new value.

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

Aside from that, I believe that you better off using a functional language like F# instead of C# if you want to follow that paradigm.

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

#7


1  

You can define a readonly variable that can only have it's value set in the objects constructor.

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

Read about it here: http://msdn.microsoft.com/en-us/library/acdd6hb7%28v=VS.100%29.aspx

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

#8


1  

It is possible to mark a field readonly which will require you set it a value either at point of declaration or in the constructor and then will prevent it from being reassigned post construction.

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

However, whilst the reference will be read-only, the object will not necessarily be so too. To prevent the object itself from being modified you will have to make the type immutable or else provide an wrapper class that only exposes the non-destructive methods and properties of the underlying type.

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

#9


0  

If you want to assign the variable at runtime after the object containing it has been constructed you could use a custom property with a setter method that can only be modified once. ie.

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

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

#1


5  

You could create your own generic class that provided this functionality, but that might be overkill.

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

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;
      }
   }
}

#2


24  

Yes, there are several ways to do that in C#.

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

First off, what is a "variable"? A variable is a storage location. Local variables, formal parameters of methods (and indexers, constructors and so on), static and instance fields, array elements and pointer dereferences are all variables.

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

Some variables can be declared as "readonly". A "readonly" variable can only be changed once, either by an initializer in the declaration, or in a constructor. Only fields declarations can be readonly; C# does not support user-declared readonly locals.

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

There are certain restrictions on readonly variables that help ensure that the normal operation of C# does not introduce a mutation. This can lead to some unexpected results! See

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

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

for details.

Some locals are effectively readonly as well. For example, when you say using(Stream s = whatever) then inside the embedded statement of the using you cannot change the value of s. The reason for this restriction is to prevent the bug whereby you create a resource that is to be disposed, and then dispose of a different resource when the contents of variable s are disposed. It had better be the same.

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

(Unfortunately there are bugs in C# involving the situation where the disposed resource is a struct type, the struct has a method which mutates the struct, and the local variable is or is not a closed-over local of an anonymous function or iterator block; since the scenarios are obscure and the fix would be potentially breaking we haven't done anything about it yet, pending further analysis.)

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

The local variable declared in a foreach statement is also effectively readonly -- that variable changes value every time through the loop, but you are not allowed to change its value.

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

There is no way to make a readonly formal parameter, array element or pointer dereference.

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

There are various ways to "break" the readonly restriction and write to a variable that is supposed to be read only. You can use Reflection or unsafe code to break pretty much any safety restriction of the CLR if you have sufficient privilege to do so. If it hurts when you do that, don't do that; with those powers comes the responsibility to know what you're doing and do it right.

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

#3


12  

You can declare a readonly variable which can be set only in the constructor or directly through its declaration.

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

#4


5  

You can roll your own using a custom setter (but don't use Object unless you have to, choose the correct class):

您可以使用自定义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;
    }
}

EDIT:

This doesn't stop the private field being changed by the class internals.

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

#5


4  

Sure. You can use readonly:

当然。您可以使用readonly:

I.e.: public readonly int z;

即:public readonly int z;

This can only be modified from within the constructor.

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

From MSDN:

You can assign a value to a readonly field only in the following contexts:

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

When the variable is initialized in the declaration, for example:

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

  • public readonly int y = 5;

    public readonly int y = 5;

  • For an instance field, in the instance constructors of the class that contains the field declaration, or for a static field, in the static constructor of the class that contains the field declaration. These are also the only contexts in which it is valid to pass a readonly field as an out or ref parameter.

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

If however you are wanting to make a property that can only be altered within the class that created it, you can use the following:

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

public string SetInClass
{
   get;
   private set;
}

This allows changes to be made within the class, but the variable cannot be altered from outside the class.

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

#6


2  

Since a similar question has been recently asked by @Ivan, let me suggest yet another method to instanciate a property at any place in the code, of course, more exactly, with the support of a generic constructor.

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

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

Usage would be

用法是

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

The point is that now you get a compile error if you try to set a new value.

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

Aside from that, I believe that you better off using a functional language like F# instead of C# if you want to follow that paradigm.

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

#7


1  

You can define a readonly variable that can only have it's value set in the objects constructor.

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

Read about it here: http://msdn.microsoft.com/en-us/library/acdd6hb7%28v=VS.100%29.aspx

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

#8


1  

It is possible to mark a field readonly which will require you set it a value either at point of declaration or in the constructor and then will prevent it from being reassigned post construction.

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

However, whilst the reference will be read-only, the object will not necessarily be so too. To prevent the object itself from being modified you will have to make the type immutable or else provide an wrapper class that only exposes the non-destructive methods and properties of the underlying type.

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

#9


0  

If you want to assign the variable at runtime after the object containing it has been constructed you could use a custom property with a setter method that can only be modified once. ie.

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

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