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

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


当前回答

常量将作为文本值编译到使用者中,而静态字符串将作为对定义值的引用。

作为练习,尝试创建一个外部库并在控制台应用程序中使用它,然后更改库中的值并重新编译它(而不重新编译用户程序),将DLL放入目录并手动运行EXE,您应该会发现常量字符串没有改变。

其他回答

这说明了这一点。概要:const必须在声明时初始化,readonly可以在构造函数上初始化(因此,根据使用的构造函数,其值不同)。

编辑:关于细微的差异,请参见上面吉树的gotcha

常量

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

只读实例字段

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

静态只读字段

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

另外,只读引用类型只会使引用只读,而不会使值只读。例如:

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};

  public UpdateReadonly()
  {
     I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
     I_RO_VALUE = new char[]{'V'}; //will cause compiler error
  }
}

它们都是常量,但在编译时也可以使用常量。这意味着差异的一个方面是,可以使用常量变量作为属性构造函数的输入,但不能使用只读变量。

例子:

public static class Text {
  public const string ConstDescription = "This can be used.";
  public readonly static string ReadonlyDescription = "Cannot be used.";
}

public class Foo 
{
  [Description(Text.ConstDescription)]
  public int BarThatBuilds {
    { get; set; }
  }

  [Description(Text.ReadOnlyDescription)]
  public int BarThatDoesNotBuild {
    { get; set; }
  }
}

还有一个陷阱:只读值可以通过反射被“狡猾”的代码改变。

var fi = this.GetType()
             .BaseType
             .GetField("_someField", 
                       BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);

我可以使用反射更改C#中的私有只读继承字段吗?