为什么在构造函数中首选对象初始化?

时间:2012-08-28 17:30:09

标签: c# java

  

可能重复:
  C# member variable initialization; best practice?
  Why should member variables be initialized in constructors?
  Should I initialize variable within constructor or outside constructor

在Java / C#中我们通常会看到

public class MyClass {
    private MyObject myObject;

    public MyClass(){
        myObject = new MyObject();
    }
}

而不是

public class MyClass {
    private MyObject myObject = new MyObject();

    public MyClass(){

    }
}

是什么原因?

2 个答案:

答案 0 :(得分:1)

没有区别,它只是一种风格选择。

在您的示例中,如果您选择第二种方法,则不必提供构造函数,这样可以节省几行代码。

答案 1 :(得分:1)

这归结为其中一条评论中所述的编码偏好。如果您编译以下代码

public class TestInitialization
{
    private object test1 = new object();
    private object test2;

    public TestInitialization()
    {
        this.test2 = new object();
    }
}

编译时,使用的实际代码如下

public class TestInitialization
{
    private object test1;
    private object test2;

    public TestInitialization()
    {
        this.test1 = new object();
        this.test2 = new object();
    }
}

所以他们完全一样,用你喜欢的。

编辑: 下面是一个带有继承类的基类和生成的已编译IL的示例。

基础课程

class basetest
{
    private object test1 = new object();
    private object test2;

    public basetest()
    {
        this.test2 = new object();
    }
}

继承类

class testclass : basetest
{
    private object testclass1 = new object();
    private object testclass2;

    public testclass() : base()
    {
        this.testclass2 = new object();
    }
}

产生的IL基类

.class private auto ansi beforefieldinit basetest
    extends [mscorlib]System.Object
{
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        .maxstack 8
        L_0000: ldarg.0 
        L_0001: newobj instance void [mscorlib]System.Object::.ctor()
        L_0006: stfld object logtest.basetest::test1
        L_000b: ldarg.0 
        L_000c: call instance void [mscorlib]System.Object::.ctor()
        L_0011: nop 
        L_0012: nop 
        L_0013: ldarg.0 
        L_0014: newobj instance void [mscorlib]System.Object::.ctor()
        L_0019: stfld object logtest.basetest::test2
        L_001e: nop 
        L_001f: ret 
    }


    .field private object test1

    .field private object test2

}

继承类IL

.class private auto ansi beforefieldinit testclass
    extends logtest.basetest
{
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
    {
        .maxstack 8
        L_0000: ldarg.0 
        L_0001: newobj instance void [mscorlib]System.Object::.ctor()
        L_0006: stfld object logtest.testclass::testclass1
        L_000b: ldarg.0 
        L_000c: call instance void logtest.basetest::.ctor()
        L_0011: nop 
        L_0012: nop 
        L_0013: ldarg.0 
        L_0014: newobj instance void [mscorlib]System.Object::.ctor()
        L_0019: stfld object logtest.testclass::testclass2
        L_001e: nop 
        L_001f: ret 
    }


    .field private object testclass1

    .field private object testclass2

}

我觉得我有点困惑。在此示例中,构造函数外部的初始化程序在调用基础构造函数之前初始化为FIRST。所以无论如何,构造函数之外的初始化器将首先在构造函数中的初始化之前初始化,并且在大多数情况下这不应该是重要的。从技术上讲,它们都被转换为在构造函数中初始化,并且适用以下规则。

  1. 首先运行构造函数之外的所有初始值设定项
  2. 所有基类构造函数都称为
  3. 构造函数中的所有初始值设定项都已运行
  4. 基本上,编译器会将构造函数之外的所有初始值设定项添加到构造函数代码中,然后正常运行。

    所以这个

    public class test : basetest
    {
        private object test1 = new object();
        private object test2;
    
        public test() : base()
        {
            this.test2 = new object();
        }
    }
    
    public class basetest
    {
        private object basetest1 = new object();
        private object basetest2;
    
        public basetest()
        {
            this.basetest2 = new object();
        }
    }
    

    变为

    public class test : basetest
    {
        private object test1;
        private object test2;
    
        public test()
        {
            //prepend everything first
            this.test1 = new object();
    
            //call base
            base(); //not legal but just an example
    
            //everything else that was already here
            this.test2 = new object();
        }
    }
    
    public class basetest
    {
        private object basetest1;
        private object basetest2;
    
        public basetest()
        {
            //prepend initializers
            this.basetest1 = new object();
    
            //if there were more base classes, the constructors would be called here
    
            //do everything else that was already here
            this.basetest2 = new object();
        }
    }
    

    希望这更有意义,并清除一些事情。我知道我有一个问题,当他们说它运行时,有些人的意思是什么,第一个"或"外面"构造函数;实际上它确实运行INSIDE一个构造函数,但所调用的顺序会受到影响。