【问题标题】:How can make a variable (not class member) "read only" in C#如何在 C# 中使变量(不是类成员)“只读”
【发布时间】:2011-01-08 17:42:38
【问题描述】:

我是 C# 世界的新手,我找不到在 C# 中声明只读变量的方法(类似于在 C++ 中声明“const”变量)。有吗?

我给你举个例子:

...
int f() { return x; } // x is not const member
...
void g() {
    int readOnlyVar = f(); // is there a method to declare readOnlyVar as read only or const

    // Some code in which I want to restrict access to readOnlyVar to read only 
}

【问题讨论】:

  • 老兄,我认为遵循 referential transparency 指南就足够了,您的 methods must be as small 让您一眼就可以知道应该做什么.

标签: c# c#-3.0 c#-4.0


【解决方案1】:

没有完全相同的类似物。

readonly 关键字允许改变变量值,但只能在构造函数中。

const关键字表示值不能变异,需要是编译时常量,只能是以下类型之一:sbyte, byte, short, ushort, int, uint, long, ulong, char, float 、double、decimal、bool、string、枚举类型或引用类型。 (C# 4.0 规范 §10.4)。

而在c#中,readonly只适用于字段,不能适用于局部变量。

【讨论】:

  • 提到const不能适用于所有数据类型
  • 完全符合我的预期,只是想确定一下,谢谢!
【解决方案2】:

不,您的代码示例没有解决方案。

C# 中的const 用于编译时常量,并且由于您的变量从函数中获取其值,因此在编译时不知道。

readonly 关键字可以满足您的需求,但这仅适用于类中的成员变量(并且只允许在类的构造函数中设置变量)。

但是,另一方面,您为什么需要它?如果你的函数很长,它应该被重构为更小的函数。如果不是很长,那么为什么需要执行这样的规则?只是不要分配给readOnlyVar 恐怕是我对你最好的建议。

【讨论】:

    【解决方案3】:

    有两种方法可以将变量设置为只读。

    public class ClassA
    {
      private const int I = 5;
      private readonly int J = 5;
    }
    

    const 关键字将在编译时设置值。 readonly 关键字将在构造时设置值。因此,如果您需要为每个实例提供不同的值,请使用只读。否则使用 const。

    【讨论】:

      【解决方案4】:

      在 c# 中,我们使用 const 或 readonly 关键字来声明一个常量。

      常量

      常量成员是在编译时定义的,不能在运行时更改。常量使用 const 关键字声明为字段,并且必须在声明时进行初始化。例如;

      public class MyClass
      {
        public const double PI = 3.14159;
      }
      

      不能在应用程序的代码中的其他任何地方更改 PI,因为这会导致编译器错误。

      只读

      只读成员就像一个常数,因为它代表一个不变的值。不同之处在于只读成员可以在运行时初始化,在构造函数中也可以在声明时初始化。例如:

      public class MyClass
      {
        public readonly double PI = 3.14159;
      }   
      

      public class MyClass
      {
        public readonly double PI;
      
        public MyClass()
        {
          PI = 3.14159;
        }
      }
      

      因为只读字段可以在声明或构造函数中初始化,所以只读字段可以具有不同的值,具体取决于使用的构造函数。只读字段也可用于运行时常量,如下例所示:

      public static readonly uint l1 = (uint)DateTime.Now.Ticks;
      

      备注

      readonly 成员不是隐式静态的,因此如果需要,可以将 static 关键字显式应用于 readonly 字段。

      只读成员可以通过在初始化时使用 new 关键字来保存复杂对象。 只读成员不能保存枚举。

      功劳在这里: http://www.dotnetspider.com/forum/69474-what-final-c-i-need-detailed-nfo.aspx

      【讨论】:

        【解决方案5】:

        这不是语言功能,而是you’re not the only person interested in such a feature。不过,您确实有一些选择。您可以将方法的实现替换为具有readonly 成员变量的类。但是,这是一个很大的痛苦,并且确实会增加代码的大小。 (当您编写 lambda 或使用 async 方法时,C# 会执行类似于将局部变量提升到类字段并将您的 lambda 或异步方法转换为自动生成类的方法的操作。我们基本上是在做同样的事情,但是手动进行以便我们可以设置readonly。)

        class Scope
        {
            int x;
        
            int f() => x; // x is not const member
        
            void g()
            {
                new gImpl(f()).Run();
            }
        
            class gImpl
            {
                readonly int readOnlyVar;
                public gImpl(
                    int readOnlyVar)
                {
                    this.readOnlyVar = readOnlyVar;
                }
                public void Run()
                {
                    // Some code in which I want to restrict access to readOnlyVar to read only 
        
                    // error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
                    readOnlyVar = 3;
                }
            }
        }
        

        另一个需要更少代码但仍然笨拙的替代方法是滥用foreach 的功能。 foreach 关键字不允许您分配给迭代变量。所以你可以这样做:

        class Scope
        {
            int x;
        
            int f() => x;
        
            void g()
            {
                foreach (var readOnlyVar in new[] { f(), })
                {
                    // Some code in which I want to restrict access to readOnlyVar to read only 
        
                    // error CS1656: Cannot assign to 'readOnlyVar' because it is a 'foreach iteration variable'
                    readOnlyVar = 3;
                }
            }
        }
        

        foreach 方法可以更轻松地使用匿名类型,但您可以将泛型与类型推断结合使用,以便通过类方法使用匿名类型。

        【讨论】:

          猜你喜欢
          • 2012-08-27
          • 1970-01-01
          • 2011-06-05
          • 1970-01-01
          • 2020-08-16
          • 1970-01-01
          • 1970-01-01
          • 2011-09-05
          • 1970-01-01
          相关资源
          最近更新 更多