循环静态只读字段定义的奇怪行为

在 Visual Studio 2017(调试版本)中运行以下代码时,我遇到了一些奇怪的行为:


using System;

using System.Collections.Generic;


namespace ConsoleApp2

{

    public class Program

    {

        public static class DefaultCustomers

        {

            public static readonly Customer NiceCustomer = new Customer() { Name = "Mr. Nice Guy " };

            public static readonly Customer EvilCustomer = new Customer() { Name = "Mr. Evil Guy " };

            public static readonly Customer BrokeCustomer = new Customer() { Name = "Mr. Broke Guy" };

        }


        public class Customer

        {

            public static readonly IEnumerable<Customer> UnwantedCustomers = new[] { DefaultCustomers.EvilCustomer, DefaultCustomers.BrokeCustomer };


            public string Name { get; set; }


            public override string ToString()

            {

                return Name;

            }

        }


        public static void Main(string[] args)

        {

            Console.WriteLine(new Customer() { Name = "Some other customer" });

            //Console.WriteLine(DefaultCustomers.NiceCustomer);


            foreach (var customer in Customer.UnwantedCustomers)

            {

                Console.WriteLine(customer != null ? customer.ToString() : "null");

            }


            Console.ReadLine();

        }

    }

}

控制台上的输出是


Some other customer

Mr. Evil Guy

Mr. Broke Guy

这大致是我预期的行为。但是,如果我取消注释 Program.Main(...) 中的第二行,输出将更改为


Some other customer

Mr. Nice Guy

null

null

我知道可以通过将 UnwantedCustomers 转换为静态只读属性来轻松解决此问题。


但我想知道所描述的行为是否遵循类和对象的初始化顺序,或者这种行为是否未定义?


ABOUTYOU
浏览 88回答 1
1回答

慕桂英3389331

你有一个初始化问题的顺序。static字段(和属性)在静态构造函数运行之前初始化(或者如果你有的话会运行)。这是在对类的任何成员的任何引用被引用(静态或非静态)之前。注释掉石灰后,当Customer.UnwantedCustomers被引用时,它会触发静态构造,Customer其前面是DefaultCustomers.但是更容易引用DefaultCustomers它会触发DefaultCustomers需要静态构造的静态构造Customer。这意味着 的静态属性在 的静态属性之前Customer初始化。因此为空。在这种情况下,一旦静态构造完成,静态构造就会完成,因此具有值但包含空值。DefaultConstomersCustomerDefaultCustomersDefaultCustomers.NiceCustomerCustomer.UnwantedCustomers这是一种定义明确的行为,可以用可预测的行为(如果没有帮助)来涵盖此类情况。您的问题是您的两种类型之间的循环引用。将UnwantedCustomers其作为一个领域DefaultCustomers将避免该问题。
打开App,查看更多内容
随时随地看视频慕课网APP