简体   繁体   English

需要对 C# 中的 static 构造函数 VS static 字段初始化器故事进行一些说明

[英]Need some clarification about the static constructor VS static field initializer story in C#

A couple of days ago I asked myself about the difference, if any, between initializing static fields via the static constructor and doing so by using a static field initializer (inline initialization of a static field at the point of declaration). A couple of days ago I asked myself about the difference, if any, between initializing static fields via the static constructor and doing so by using a static field initializer (inline initialization of a static field at the point of declaration).

After reading plenty of stackoverflow questions on the subject and the famous Jon Skeet's article on the beforefieldinit flag I've now a much better understanding of the difference between the two initialization strategies.在阅读了大量关于该主题的 stackoverflow 问题和著名的 Jon Skeet 关于 beforefieldinit 标志的文章之后,我现在对两种初始化策略之间的区别有了更好的理解。

There is one point that I'm not sure about, mostly because I wasn't able to find any official documentation about it.有一点我不确定,主要是因为我找不到任何关于它的官方文档。

The static construcutor is guaranteed to be executed only once and I think this holds true even in multi threading scenarios (when different threads create instances of the class and / or use static members of the class. In any case, the static constructor runs once and only once). The static construcutor is guaranteed to be executed only once and I think this holds true even in multi threading scenarios (when different threads create instances of the class and / or use static members of the class. In any case, the static constructor runs once and只有一次)。

Is this true even for the inline initialization of the static fields?即使对于 static 字段的内联初始化也是如此吗? Is the inline initialization of a static field guaranteed to be executed once even in multi threaded scenarios?即使在多线程场景中,static 字段的内联初始化是否也保证执行一次?

Another point I'm still missing is what are the practical consequences of this difference in the initialization of the static fields of a class.我仍然缺少的另一点是在 class 的 static 字段的初始化中这种差异的实际后果是什么。 Put another way, I would like to understand when the correctness of a piece of code can be affected by the choice of initializing a static fied inline at the point of declaration (instead of using the static constructor).换句话说,我想了解一段代码的正确性何时会受到选择在声明时内联初始化 static 的选择(而不是使用 static 构造函数)的影响。

Most of the time (this depends mostly on the type of code that I usually work on, namely web applications) I use static readonly fields in service classes to store things that are used by the service I'm writing to perform computations or taking decisions.大多数时候(这主要取决于我通常处理的代码类型,即 web 应用程序)我在服务类中使用 static 只读字段来存储我正在编写的服务用于执行计算或做出决策的内容. I decide to put these things inside static fields because they need to be the same for all the possible instances of the class I'm writing, they are actually invariants that don't belong to a particular instance, but instead they belong to the algorithm itself.我决定将这些东西放在 static 字段中,因为对于我正在编写的 class 的所有可能实例,它们需要相同,它们实际上是不属于特定实例的不变量,而是属于算法本身。

This is an example:这是一个例子:

public class SomeInterestingService 
{
   private static readonly int ConstantNumber = 13;
   private static readonly string[] Names = new[] { "bob", "alice" };

   private readonly INumberGenerator numberGenerator;

   public SomeInterestingService(INumberGenerator numberGenerator)
   {
      this.numberGenerator = numberGenerator ?? throw new ArgumenNullException(nameof(numberGenerator));
   }

   public int ComputeMagicNumber() 
   {
      int answer = this.numberGenerator.GetNumber();

       foreach(var name in names)
       {
          answer += name.Length;
       }

       answer += ConstantNumber;
       return answer;
   }
}

In code like this, is there any practical difference in chosing static constructor initialization or inline initialization of the static fields ConstantNumber and Names , apart from the difference in performance (inline initialization is more performant due to runtime optimizations that are not possible when using the static constructor)? In code like this, is there any practical difference in chosing static constructor initialization or inline initialization of the static fields ConstantNumber and Names , apart from the difference in performance (inline initialization is more performant due to runtime optimizations that are not possible when using the static构造函数)?

Can the correctness of the code above be affected by the coiche in any strange corner case?在任何奇怪的极端情况下,上面代码的正确性会受到 coiche 的影响吗? (I think not) (我想不是)

Original question:原始问题:

In code like this, is there any practical difference in chosing static constructor initialization or inline initialization of the static fields ConstantNumber and Names, apart from the difference in performance (inline initialization is more performant due to runtime optimizations that are not possible when using the static constructor)? In code like this, is there any practical difference in chosing static constructor initialization or inline initialization of the static fields ConstantNumber and Names, apart from the difference in performance (inline initialization is more performant due to runtime optimizations that are not possible when using the static构造函数)?

The answer is no.答案是不。 Either those properties are set upon each construction of the class (instance properties) or set upon the first call to any of the members or methods to the class (static properties).这些属性要么在每次构造 class(实例属性)时设置,要么在第一次调用 class(静态属性)的任何成员或方法时设置。

What @Henk Holterman is saying that because the array of names is a reference type you could theoretically change any of the values in the array. @Henk Holterman 所说的是因为名称数组是一种引用类型,理论上您可以更改数组中的任何值。 Like:喜欢:

Names[0] = "Henk Holterman";

Even though the property is readonly.即使该属性是只读的。 Meaning, you can't assign a new instance of array to that property.这意味着,您不能将数组的新实例分配给该属性。 The values in the array are not readonly.数组中的值不是只读的。 And could be manipulated if public or by calling a method of that class.如果公开或通过调用该 class 的方法,则可以对其进行操作。

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

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