混合构造函数集字段和字段初始值设定项

时间:2013-02-25 16:08:56

标签: c# oop

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

示例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传递给声明时初始化的字段。我关注的主要是与上述七个例子类似的情况。我是否通过这种方式将它们混合在一起来解决任何不可预见的问题?

2 个答案:

答案 0 :(得分:2)

通常,无论是在构造函数中初始化字段还是使用字段初始值设定项,都无关紧要。但是,关于操作的时间和顺序,您应该注意一些细微之处:

  • 实例字段初始值设定项和实例构造函数按以下顺序运行,这可能会令人惊讶:

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

请参阅Eric Lippert撰写的文章,讨论此行为的原因:http://blogs.msdn.com/b/ericlippert/archive/2008/02/18/why-do-initializers-run-in-the-opposite-order-as-constructors-part-two.aspx

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

答案 1 :(得分: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/