在C#中常量和只读之间有什么区别?

你什么时候会用一个代替另一个?


当前回答

ReadOnly:该值只能从类的构造函数初始化一次。const:可以在任何函数中初始化,但只能初始化一次

其他回答

除了

必须在常量VS只读值的定义时声明该值可以动态计算,但需要在构造函数退出之前赋值。之后,它被冷冻。常量是隐式静态的。您使用ClassName.ConstantName符号来访问它们。

有一个微妙的区别。考虑AssemblyA中定义的类。

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly int I_RO_VALUE;
  public Const_V_Readonly()
  {
     I_RO_VALUE = 3;
  }
}

AssemblyB引用AssemblyA并在代码中使用这些值。编译时:

对于常量值,它就像查找替换。值2被“烘焙”到AssemblyB的IL中。这意味着如果明天我将I_CONST_value更新为20,AssemblyB仍将有2,直到我重新编译它。在只读值的情况下,它类似于对内存位置的引用。该值不会烘焙到AssemblyB的IL中。这意味着如果更新了内存位置,AssemblyB将在不重新编译的情况下获得新值。因此,如果I_RO_VALUE更新为30,则只需要构建AssemblyA,而不需要重新编译所有客户端。

因此,如果你确信常数的值不会改变,那么使用常量。

public const int CM_IN_A_METER = 100;

但是,如果您有一个可能会改变的常数(例如w.r.t.精度),或者当有疑问时,请使用只读。

public readonly float PI = 3.14;

更新:阿库需要被提及,因为他首先指出了这一点。此外,我需要插入我学到的内容:有效的C#-比尔·瓦格纳

C#.Net中常量字段和只读字段之间存在显著差异

const在默认情况下是静态的,需要用常量值初始化,以后不能修改。构造函数中也不允许更改值。它不能与所有数据类型一起使用。对于ex-DateTime。它不能与DateTime数据类型一起使用。

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public readonly string Name = string.Empty; //No error, legal

只读可以声明为静态,但不是必需的。无需在声明时进行初始化。它的值可以使用构造函数赋值或更改。因此,它在用作实例类成员时具有优势。两个不同的实例化可能具有不同的只读字段值。对于ex-

class A
{
    public readonly int Id;

    public A(int i)
    {
        Id = i;
    }
}

然后,只读字段可以用即时特定值初始化,如下所示:

A objOne = new A(5);
A objTwo = new A(10);

这里,实例objOne的只读字段值为5,objTwo的值为10。这不可能使用常量。

const是编译时常量,而readonly允许在运行时计算值并在构造函数或字段初始值设定项中设置。因此,“const”总是常量,但“readonly”在赋值后是只读的。

C#团队的埃里克·里佩尔(Eric Lippert)有更多关于不同类型不变性的信息。

常量

默认情况下,常量是静态的它们在编译时必须有一个值(例如3.14*2,但不能调用方法)无法在函数中声明复制到使用它们的每个程序集中(每个程序集都获得值的本地副本)可用于属性

只读实例字段

在构造函数退出时必须具有设置值在创建实例时计算

静态只读字段

当代码执行命中类引用时(当创建新实例或执行静态方法时)在完成静态构造函数时必须具有计算值不建议将ThreadStaticAttribute放在这些线程上(静态构造函数将仅在一个线程中执行,并将为其线程设置值;所有其他线程将未初始化此值)

我相信常量值对于所有对象都是相同的(并且必须用文字表达式初始化),而只读对于每个实例化可以是不同的。。。