类声明v / s构造函数内部初始化对象的区别

时间:2019-01-30 17:41:20

标签: c# oop constructor object-initializers

我正在为我的对象进行对象初始化和构造函数初始化,但是无法获得对我的问题的确切答复。 这里的Case1和Case2有什么区别?

案例1:

namespace ConsoleApplication2
{
    class MyBuilder
    {
        private MySynchronizer m_synchronizer = new MySynchronizer();

        public MyBuilder()
        {

        }

        public void ProcessRecord(int recordNumber)
        {
            m_synchronizer.Process(recordNumber);
        }
    }
}

第二种情况:

namespace ConsoleApplication2
{
    class MyBuilder
    {
        private MySynchronizer m_synchronizer;

        public MyBuilder()
        {
          m_synchronizer = new MySynchronizer();

        }

        public void ProcessRecord(int recordNumber)
        {
            m_synchronizer.Process(recordNumber);
        }
    }
}

这是示例代码,显示了我如何调用Builder类;

 class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Press any key to stop");
            MyBuilder builder = new MyBuilder();
            builder.ProcessRecord(2);
        }
    }

[对不起,如果我不能正确地改写问题,在这种情况下,任何人都可以提供指向其他SO文章的链接]

3 个答案:

答案 0 :(得分:4)

这里的区别是确实细微,只能在IL中轻松欣赏:

ArrayList

为我们提供了构造函数:

class MyBuilder1
{
    private MySynchronizer m_synchronizer = new MySynchronizer();

    public MyBuilder1()
    {

    }
}

位置-

.method public hidebysig specialname rtspecialname 
    instance void .ctor () cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 18 (0x12)
    .maxstack 8

    IL_0000: ldarg.0
    IL_0001: newobj instance void MySynchronizer::.ctor()
    IL_0006: stfld class MySynchronizer MyBuilder1::m_synchronizer
    IL_000b: ldarg.0
    IL_000c: call instance void [mscorlib]System.Object::.ctor()
    IL_0011: ret
} // end of method MyBuilder1::.ctor

给予我们

class MyBuilder2
{
    private MySynchronizer m_synchronizer;

    public MyBuilder2()
    {
      m_synchronizer = new MySynchronizer();

    }
}

区别只是订购之一:

  • 字段初始化器(// Methods .method public hidebysig specialname rtspecialname instance void .ctor () cil managed { // Method begins at RVA 0x2063 // Code size 18 (0x12) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: ldarg.0 IL_0007: newobj instance void MySynchronizer::.ctor() IL_000c: stfld class MySynchronizer MyBuilder2::m_synchronizer IL_0011: ret } // end of method MyBuilder2::.ctor )发生在基本类型构造函数调用之前(<{>} (MyBuilder1是此处的基础; object是基本构造函数的调用)
  • 构造函数发生在 基本类型构造函数调用之后

在大多数情况下,这无关紧要。除非您的基本构造函数调用派生类型将覆盖的虚拟方法:否则,字段在覆盖方法中是否具有值将在两者之间有所不同。

答案 1 :(得分:1)

正如@Marc已经提到的,区别在于基本构造函数的顺序。

我添加了基本构造函数

 class Base
    {
        public Base()
        {
            Console.WriteLine("Inside Base constructor");
        }
    }

并将我的类“ MyBuilder”修改为从其派生为;

 class MyBuilder : Base
    {

    }

现在,case1的输出如下:

enter image description here

而案例2:

enter image description here

因此

  • 如果您有多个构造函数,则case1方法可能会更好,因为不容易出错,因为有人可以轻松添加另一个构造函数而忘记链接它。
  • 如果您具有单个构造函数,并且没有任何依赖于基本构造函数顺序的逻辑流程,则case2似乎更好,因为这将使代码更简洁。 [无犯罪行为,个人喜好]

答案 2 :(得分:0)

我几乎总是选择第二个选项(在构造函数内部初始化)。以我的观点,它可以使您的代码更具可读性,并且控制逻辑位于构造函数内部,这为将来添加逻辑提供了更大的灵活性。

但同样,这只是我个人的看法。