初始化优先级 - const vs readonly vs static readonly

时间:2012-08-09 19:27:06

标签: c# .net

示例1

private const string _DefaultIconPath = _IconsPath + "default.ico";
private const string _IconsPath = "Icons/";

运行时这些字符串的值:

  • _DefaultIconPath:“Icons / default.ico”
  • _IconsPath:“Icons /”

示例2

private readonly string _DefaultIconPath = _IconsPath + "default.ico";
private readonly string _IconsPath = "Icons/";

编译时间错误:

A field initializer cannot reference the non-static field, method, or property '_IconsPath'

示例3

private static readonly string _DefaultIconPath = _IconsPath + "default.ico";
private static readonly string _IconsPath = "Icons/";

运行时这些字符串的值:

  • _DefaultIconPath:“default.ico”(_IconsPath评估为null
  • _IconsPath:“Icons /”

问题

为什么编译器在示例3中没有抛出类似于示例2的编译错误?

声明的顺序在static readonly字段定义的情况下很重要,但在const字段定义的情况下则不重要。

编辑:

我理解为什么字符串被初始化为那些特定的值。我不明白的是为什么示例2抛出编译错误,强制初始化发生在构造函数而不是变量声明中(这很有意义),但是示例3的行为方式并不相同。抛出相同的编译错误强制在静态构造函数中进行初始化是不是有意义?


另一个例子

private static string test = test2;
private static string test2 = test;

此示例演示了我要解释的内容。编译器可以强制在静态构造函数中初始化静态(就像实例变量一样)。为什么编译器允许它(或者为什么编译器不允许这个实例变量)?

3 个答案:

答案 0 :(得分:0)

有两个无关的问题。

<强> 1。编译错误

静态成员不需要类的实例来获取值。这就是从静态成员引用静态成员不会导致问题的原因。

初始化实例成员时,除非您从构造函数中执行此操作,否则在尝试初始化成员时无法引用this

因为您没有将Example 2中的字段标记为static,所以在引用这些成员之前,必须首先实例化包含它们的任何对象的实例。

仅仅因为它们readonly并不意味着它们是static。只读字段可以在它们的声明或类的构造函数中实例化,但它们不会在类的所有实例中共享,也不能在没有适当实例化的情况下访问它们(假设它们没有明确地static Example 3 {1}})。

<强> 2。空值

_IconsPathExample 3为空的原因是因为字段是按顺序声明和实例化的。颠倒顺序,你会发现它不再是空的。

答案 1 :(得分:0)

示例3使用static变量,因此允许使用。

示例2失败,因为C#不允许变量初始化程序引用正在创建的实例。请参阅Jon Skeet的解释here

你可以这样做:

public class YourClass {
  private readonly string _IconsPath;
  private readonly string _DefaultIconsPath;

  public YourClass() {
    _IconsPath = "Icons/";
    _DefaultIconPath = _IconsPath + "default.ico";
  }
}

答案 2 :(得分:0)

在示例2&#39; _IconsPath&#39;没有初始化,也无法使用。

在示例3中,您正在访问静态字段(如您所知)。 MSDN A static method, field, property, or event is callable on a class even when no instance of the class has been created.

表示完全没问题

here

更新: 例3:它与:

相同
private static readonly string _DefaultIconPath = MyStaticClass._IconsPath + "default.ico";
private static readonly string _IconsPath = "Icons/";

关键是你没有使用一个字段(没有初始化的belove,你正在使用(&#34;其他&#34; /&#34; new&#34;)静态类(那个dosn&在以静态方式使用它之前必须先创建它。)