如何在C#中使变量(不是类成员)“只读”

时间:2011-01-08 17:42:39

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

我是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 
}

5 个答案:

答案 0 :(得分:11)

没有相同的类比。

readonly关键字允许变量值变异,但仅限于构造函数。

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

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

答案 1 :(得分:4)

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

C#中的

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

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

但是,另一方面,你为什么需要呢?如果你的函数很长,它应该被重构成更小的函数。如果它不是很长,那你为什么要强制执行这样的规则呢?只是不指定给readOnlyVar可能是我最好的建议,我害怕。

答案 2 :(得分:2)

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

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

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

答案 3 :(得分:1)

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

<强>常量

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

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

在代码中的任何其他地方都无法更改PI,因为这会导致编译器错误。

<强>只读

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

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

public class MyClass
{
  public readonly double PI;

  public MyClass()
  {
    PI = 3.14159;
  }
}

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

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

备注

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

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

信誉来到这里: http://www.dotnetspider.com/forum/69474-what-final-c-i-need-detailed-nfo.aspx

答案 4 :(得分:0)

这不是语言功能,而是you’re not the only person interested in such a feature。不过,你确实有一些选择。您可以使用具有readonly成员变量的类替换方法的实现。但这是一个巨大的痛苦,并且真正爆炸了代码的大小。 (当你编写lambdas或使用async方法时,C#会做类似于将locals提升到类字段并将lambda或async方法转换为自动生成类的方法。我们基本上做同样的事情,但是手动使得我们可以设置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方法可以更容易地使用匿名类型,但您可以使用泛型与类型推断相结合来使用类方法的匿名类型。