无法修改的变量

发布于 2024-09-18 04:48:07 字数 94 浏览 11 评论 0原文

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

窗影残 2024-09-25 04:48:08

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

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

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.

private myVariable = null;
public object MyVariable
{
   get { return myVariable; }
   set { if(myVariable == null ) myVariable = value;
}
月下凄凉 2024-09-25 04:48:07

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

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

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

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

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

了解详细信息。

一些当地人实际上也是只读的。例如,当您说 using(Stream s =whatever) 时,在 using 的嵌入语句中,您无法更改 s 的值。此限制的原因是为了防止出现错误,即您创建要释放的资源,然后在释放变量 s 的内容时释放不同的资源。最好是一样的。

(不幸的是,C# 中存在一些错误,涉及以下情况:所释放的资源是结构体类型,该结构体具有改变该结构体的方法,并且局部变量是或不是匿名函数或迭代器块的封闭局部变量;由于场景模糊且修复可能会造成破坏,因此我们尚未对此采取任何措施,有待进一步分析。)

foreach 语句中声明的局部变量实际上也是 readonly< /code> ——该变量每次循环都会更改值,但不允许更改其值。

无法对只读形式参数、数组元素或指针进行取消引用。

有多种方法可以“打破”只读限制并写入应该只读的变量。如果您有足够的权限,您可以使用反射或不安全代码来打破 CLR 的几乎所有安全限制。如果这样做时感到疼痛,就不要这样做;有了这些权力,就有责任知道自己在做什么并正确地做。

Yes, there are several ways to do that in 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.

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

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.

(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.)

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.

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.

彩虹直至黑白 2024-09-25 04:48:07

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

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

彼岸花ソ最美的依靠 2024-09-25 04:48:07

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

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

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;
      }
   }
}
单调的奢华 2024-09-25 04:48:07

当然。您可以使用readonly

即:public readonly int z;

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

来自 MSDN

您可以为仅在以下上下文中为只读字段:

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

  • public readonly int y = 5;

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

然而,如果您想要创建一个只能在创建它的类中更改的属性,您可以使用以下内容:

public string SetInClass
{
   get;
   private set;
}

这允许在类中进行更改,但变量不能被更改来自课堂之外。

Sure. You can use readonly:

I.e.: 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;

  • 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.

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.

赏烟花じ飞满天 2024-09-25 04:48:07

您可以使用自定义设置器来推出自己的设置器(但不要使用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;
    }
}

编辑:

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

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

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.

满栀 2024-09-25 04:48:07

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

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

用法是

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

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

除此之外,我相信如果您想遵循该范例,最好使用 F# 等函数式语言而不是 C#。

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.

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.

小帐篷 2024-09-25 04:48:07

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

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

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

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

然而,虽然引用是只读的,但对象不一定也是只读的。为了防止对象本身被修改,您必须使类型不可变,或者提供一个仅公开基础类型的非破坏性方法和属性的包装类。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文