简体   繁体   English

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

[英]Initialization precedence - const vs readonly vs static readonly

Example 1 例1

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

Value of these strings at runtime: 这些字符串在运行时的值:

  • _DefaultIconPath: "Icons/default.ico" _DefaultIconPath:“Icons / default.ico”
  • _IconsPath: "Icons/" _IconsPath:“图标/”

Example 2 例2

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

Compile time error: 编译时间错误:

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

Example 3 例3

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

Value of these strings at runtime: 这些字符串在运行时的值:

  • _DefaultIconPath: "default.ico" (_IconsPath evaluated to null ) _DefaultIconPath:“default.ico”(_IconsPath评估为null
  • _IconsPath: "Icons/" _IconsPath:“图标/”

Question

Why doesn't the compiler throw a compilation error in example 3 similar to example 2? 为什么编译器在示例3中抛出编译错误,类似于示例2?

The order of the declaration matters in the case of static readonly field definitions, but not in the case of const field definitions. 声明的顺序在static readonly字段定义的情况下很重要,但在const字段定义的情况下则不重要。

Edit: 编辑:

I understand why the strings are initialized to those specific values. 我理解为什么字符串被初始化为那些特定的值。 What I don't understand is why Example 2 throws a compilation error, forcing initialization to occur in a constructor rather than in the declaration of the variables (which makes perfect sense), but Example 3 doesn't behave in the same manner. 我不明白的是为什么示例2抛出编译错误,强制初始化发生在构造函数而不是变量声明中(这很有意义),但是示例3的行为方式并不相同。 Wouldn't it make sense to throw the same compilation error forcing the initialization to occur in a static constructor? 抛出相同的编译错误强制在静态构造函数中进行初始化是不是有意义?


Another Example 另一个例子

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

This example demonstrates what I'm trying to explain. 这个例子说明了我想要解释的内容。 The compiler could force initialization of static state in a static constructor (as is does for instance variables). 编译器可以强制在静态构造函数中初始化静态(就像实例变量一样)。 Why does the compiler allow it (or why does the compiler disallow this for instance variables)? 为什么编译器允许它(或者为什么编译器不允许这个实例变量)?

There are two unrelated problems. 有两个无关的问题。

1. Compilation Error 1.编译错误

Static members do not require an instance of a class to obtain the values. 静态成员不需要类的实例来获取值。 This is why referencing a static member from a static member does not cause problems. 这就是从静态成员引用静态成员不会导致问题的原因。

When initializing instance members, you cannot reference this when attempting to initialize members unless you do so from the constructor. 初始化实例成员时,除非从构造函数执行此操作,否则在尝试初始化成员时不能引用this

Because you have not marked the fields in Example 2 as static , you must first instantiate an instance of whatever object contains them prior to referencing those members. 因为您没有将Example 2的字段标记为static ,所以必须首先实例化包含它们的任何对象的实例,然后再引用这些成员。

Just because they are readonly does not mean that they are static . 仅仅因为它们是readonly并不意味着它们是static Readonly fields can be instantiated in their declaration or the constructor of the class, but they are not shared across all instances of the class, nor can they be accessed without proper instantiation (assuming they aren't explicitly made static like Example 3 ). 只读字段可以在它们的声明或类的构造函数中实例化,但它们不会在类的所有实例中共享,也不能在没有适当实例化的情况下访问它们(假设它们没有像Example 3那样明确地变为static )。

2. Null Value 2.空值

The reason _IconsPath is null in Example 3 is because the fields are declared and instantiated sequentially. Example 3 _IconsPath为null的原因是因为字段是按顺序声明和实例化的。 Reverse the order and you'll see that it is no longer null. 颠倒顺序,你会发现它不再是空的。

Example 3 uses static variables and so it is allowed. 示例3使用static变量,因此允许使用。

Example 2 fails because C# does not allow a variable initializer to refer the instance being created. 示例2失败,因为C#不允许变量初始化程序引用正在创建的实例。 Refer Jon Skeet's explanation here . 请参阅乔恩斯基特的解释在这里

You could do this instead: 你可以这样做:

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

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

In example 2 '_IconsPath' isn't initialized, and can not be used. 在示例2中,'_IconsPath'未初始化,无法使用。

In example 3, you are accessing a static field (as you know). 在示例3中,您正在访问静态字段(如您所知)。 It perfectly fine says MSDN A static method, field, property, or event is callable on a class even when no instance of the class has been created. MSDN A static method, field, property, or event is callable on a class even when no instance of the class has been created.

See it here 在这里看到它

Update: Example 3: It's the same as: 更新:示例3:它与以下内容相同:

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

The point is that your not using a field (belove that isn't initialized, you are using an ("other"/"new") static class (That dosn't have to be create before you used it in a static way). 关键是你没有使用一个字段(belove没有初始化,你正在使用一个(“其他”/“新”)静态类(在你以静态方式使用它之前不必创建) 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM