3

在设计类时,是否有关于初始化类字段的指导方针?有两种不同的初始化方法。我可以使用内联字段初始化程序,也可以在构造函数中初始化它们。它变得更加...有趣,当引入静态字段时,可以在定义时,在静态构造函数中或在实例构造函数中初始化字段,并检查该字段是否已设置。当引入工厂时,这变得更加混乱。

示例 1 - 内联初始化


    public class ExampleOne
    {
        private readonly IDictionary _collection = new Dictionary();

        ...
    }       

示例 2 - 构造函数初始化


    public class ExampleTwo
    {
        private readonly IDictionary _collection;

        public ExampleTwo() 
        {
            _collection = new Dictionary();
        }
        ...
    }       

示例 3 - 静态内联初始化


    public class ExampleThree
    {
        private static readonly IDictionary __collection = new Dictionary();

        ...
    }       

示例 4 - 静态构造函数初始化


    public class ExampleFour
    {
        private static IDictionary __collection;

        static ExampleFour() 
        {
            _collection = new Dictionary();
        }

        ...
    }       

示例 5 - 静态/实例构造函数混合初始化


    public class ExampleFive
    {
        private static readonly IDictionary __collection;
        private static IDictionary __anotherCollection;

        static ExampleFive() 
        {
            _collection = new Dictionary();
        }

        public ExampleFive()
        {
           if( __anotherCollection == null ) 
           {
            __anotherCollection = new Dictionary();
           }
        }

        ...
    }       

示例 6 - 工厂方法


    public class ExampleSix
    {
        private static readonly IDictionary __collection;
        private static IDictionary __anotherCollection;

        static ExampleSix() 
        {
            _collection = new Dictionary();
        }

        public static ExampleSix Create()
        {
           if( __anotherCollection == null ) 
           {
            __anotherCollection = new Dictionary();
           }

           var example = new ExampleSix();
           return example;
        }

        ...
    }       

目前,我所拥有的课程倾向于混合所有这些。尽管我试图避免在实例构造函数中设置静态字段。

示例 7 - 混合


    public class ExampleSeven
    {
        private static readonly IDictionary __collection = new Dictionary();
        private static readonly IDictionary __anotherCollection;
        private static readonly IDictionary __thirdCollection;
        private static IDictionary __fourthCollection;

        static ExampleSeven() 
        {
            __anotherCollection = new Dictionary();
        }

        public ExampleSeven() 
        {
            if( __thirdCollection == null )
            {
               __thirdCollection = new Dictionary();
            }
        }

        public static ExampleSeven Create()
        {
           if( __fourthCollection == null ) 
           {
            __fourthCollection = new Dictionary();
           }

           var example = new ExampleSeven();
           return example;
        }

        ...
    }       

我更关心的是,从示例中可以看出,字段是类对象而不是简单的原语。我知道在声明字段时初始化字段会将类标记为beforeinit,并且我无法传递this到声明时初始化的字段中。我关心的主要是与上述七个例子类似的情况。通过这种方式混合它们,我是否会为任何不可预见的问题做好准备?

4

2 回答 2

2

通常,是在构造函数中初始化字段还是使用字段初始化器并不重要。但是,关于操作的时间和顺序,您应该注意一些细微之处:

  • 实例字段初始化器和实例构造器按以下顺序运行,这可能会令人惊讶:

    • 派生类字段初始值设定项
    • 基类字段初始化器
    • 基类构造函数
    • 派生类构造函数

有关此行为原因的讨论,请参阅 Eric Lippert 的这篇文章:http: //blogs.msdn.com/b/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-相反顺序作为构造函数的第二部分.aspx

要回答您的问题,对于应该在哪里初始化字段没有明确的规则。有时,如果初始化很短,则初始化字段“inline”会更自然,但如果初始化很长,它可能应该在构造函数中。有时必须在构造函数中初始化字段,因为字段初始化程序不能包含对this. 我的代码中经常混合使用这两种样式,到目前为止,我并没有因此而遇到问题。请记住上面提到的执行顺序......

于 2013-02-25T16:32:17.120 回答
0

这个问题不只有一个答案。相反,这取决于您想在现场存储什么样的东西以及您想用它做什么。

首先,问问自己:ExampleX 是否绝对需要该字段中的对象?ExampleX 的所有用例都绝对涉及该领域吗?如果不是,则不应在构造函数中创建它。如果它仅用于一种方法,则应在该方法中创建(或传入)该方法。如果它用在两个以上的方法中,那么这些可能应该在它们自己的类中,即将类分成两个,一个依赖于该字段中的对象,一个不依赖于该字段中的对象。

其次,您真的每次创建 ExampleX 时都需要一个新字典吗?让我们换个例子——它不是字典,而是某种提供服务的对象,设置起来很昂贵,但很容易重用。在这种情况下,您绝对应该传递它而不是创建它 - 如果您创建一个新的,您会浪费资源,并且会使您的程序更复杂且可读性更低,因为您引入了隐藏的依赖项。通过传入对象,您可以在构造函数签名(或方法签名,如果您将其传递给方法)中宣传依赖关系。更不用说使它不可测试或难以测试(在单元测试的意义上)。见http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/

所以,总结一下——你总是需要它吗?这告诉您是在构造函数中还是在其他地方创建/传入对象。它必须是一个新的吗?这将告诉您是创建它还是传递它。

传递东西也让你的代码更加灵活。见http://www.kevinwilliampang.com/2009/11/07/dependency-injection-for-dummies/

于 2013-02-25T16:52:50.067 回答