调用方法在构造函数内部或外部之间的差异

时间:2013-01-09 12:02:40

标签: c# oop compiler-construction constructor instantiation

  

可能重复:
  Best Practice: Initialize class fields in constructor or at declaration?

这只是我和我的朋友在谈论我们当前项目时提出的一个简单甚至有点愚蠢的怀疑。

我想知道的是使用C#调用在类的构造函数内外设置变量的方法之间的区别,如下例所示:

案例1:

public class Test
{
    string myVar = GetValue();

    public Test()
    {
    }
}

案例2:

public class Test
{
    string myVar;

    public Test()
    {
        myVar = GetValue(); 
    }
}

使用这些方法时是否存在性能差异或任何“模式违规”?如果有人能告诉我哪种方法更好,以及在编译器级别使用它们时会发生什么,我真的很感激。

提前致谢!

4 个答案:

答案 0 :(得分:1)

AFAIK唯一的区别是首先触发字段初始化(你的第一个例子) - 它仍然基本上被视为构造函数代码。选择一个而不是另一个没有性能提升,这确实是一个偏好问题。

要注意的一点是execution order,因为它可以根据您的类层次结构进行更改。

答案 1 :(得分:1)

如果您的方法GetValue是您班级中的静态方法,那么您可以在字段初始化中使用它。如果是实例方法,则会出现错误。

您的第一个代码是使用字段初始化,而在第二个代码中,您正在构造函数中初始化字段。

Fields C#

  

字段在构造函数之前立即初始化   调用对象实例,因此如果构造函数赋值   一个字段,它将覆盖字段声明期间给出的任何值。

至于哪一个更好,我会说这取决于您的要求。通常,如果要将某个参数传递给要分配给某个字段的构造函数,则只能在构造函数中执行此操作。但是如果你想为这些字段设置一些默认值,那么在执行构造函数之前就可以使用Field Initializer了。

答案 2 :(得分:0)

下一种情况下,字段初始化可行且获得可读性的一种情况

class Test
{
    string myVar;
    string anotherVar;

    public Test()
    {
        myVar = "one default";
        anotherVar = "another default";
    }
    public Test(string s) //: this()
    {
        myVar = s;
        anotherVar = "another default";
    }
}

你可能不希望默认调用构造函数,因为在某些情况下可能是错误的来初始化一些变量两次(在我的情况下它确定是正确的);所以在上面的例子中,我会将anotherVar移动到字段初始化。

注意:谈论性能,我没有在这样的纳米优化级别上 - 当你使用字段初始化你的字段时,根据需要接收它的第一个值。当你从构造函数初始化它时,它已经有了它的默认值,所以从技术上讲你分配了一个字段两次。但是这种惩罚是如此之小,以至于我无法想象这种情况,这种情况似乎是合情合理的。

答案 3 :(得分:0)

你发布的代码没有编译,所以我继续做了几个可能的变化。

1。静态字段和静态方法

public class Test
{
    static string myVar = GetValue();

    public Test()
    {
    }

    static string GetValue()
    {
        return String.Empty;
    }
}

在这种情况下,设置静态字段的位置并不重要:在静态构造函数中(未在代码中显示)或静态字段初始化。当类型加载到AppDomain时,CLR将初始化。 (有一个序列,比如CLR首先调用静态构造函数,然后将所有静态字段设置为反之亦然 - 这个序列不在您的控制范围内)。

2。在构造函数中设置属性

public class Test1
{
    string MyVar{get;set;}

    public Test1()
    {
        MyVar = GetValue();
    }

    string GetValue()
    {
        return String.Empty;
    }
}

这取决于类型和用法。在这种特殊情况下,我可能会避免这样做,因为构造函数意味着轻量级。如果您进行任何繁重的处理,最好将其移至Initialize方法,并使用正确的错误处理和try-catch块。如果你没有做任何繁重的设置属性 - 只需在构造函数中添加一个默认值,例如MyVar = "EMPTY"

3。在另一个类

中设置属性
public class Test
{
    public string MyVar{get;set;}

    public Test(){ }

    public string GetValue()
    {
        return String.Empty;
    }
}

//somewere else 
Test t = new Test();
t.MyVar = t.GetValue();

这看起来有点奇怪,因为类提供了一个状态(属性)并且意味着获取当前状态(GetValue方法)。在这种情况下,两个成员(属性和方法)可能合并为一个 getter