使用对象初始化器有什么好处吗?

66

3
这是一种语法糖,可以节省键入代码的时间,并使代码能够放在单个可执行语句中(例如内联linq调用)。这种风格也被用于创建匿名类型:new { FirstName = "Adam", Age = 27 }; - Adam Houldsworth
请不要在问题标题中包含使用的编程语言信息,除非没有标签可能会变得没有意义。标签就是为此目的服务。 - Ondrej Janacek
您编辑了18个月前的问题。 - Sandeep Singh Rawat
10
只要有充分的理由,修改旧帖子并没有错。 - user456814
5个回答

116

经常被忽视的一个好处是原子性。如果您在对象上使用双重检查锁定,这将非常有用。对象初始化程序在初始化您告诉它的所有成员之后返回新对象。根据MSDN文章中的示例:

StudentName student = new StudentName
{
    FirstName = "Craig",
    LastName = "Playstead",
    ID = 116
};

会被翻译成类似以下的内容:

StudentName _tempStudent = new StudentName();
_tempStudent.FirstName = "Craig";
_tempStudent.LastName = "Playstead";
_tempStudent.ID = 116;

StudentName student = _tempStudent;

这样做可以确保student永远不会被部分初始化。它要么是null,要么完全初始化,这在多线程场景中很有用。

如果想了解更多信息,可以查看此文章

另一个好处是,它允许您创建匿名对象(例如,在LINQ中创建投影或在多个键上进行连接)。


4
如果在StudentName的构造函数中初始化FirstNameLastNameID,那么原子性不就得以保留了吗? - Songo
3
是的,这样做会起到作用。上述关于原子性的声明是针对当您需要在构造函数外部初始化对象属性时的情况。其中一些示例包括无法更改构造函数代码的情况,或者您的对象具有大量可选属性,想要设置这些属性而不创建过多的重载构造函数。 - Jon Senchyna

48

不使用对象初始化器的一个潜在原因是:如果在初始化过程中出现异常,Visual Studio调试器中的调用堆栈将仅返回初始化表达式而不是引发异常发生的特定行。

如果您使用具有名称不当的异常的库或外部服务,或者使用具有本地代码的库(例如在Android上的Xamarin)而无法查看引发异常的代码,则对象初始化器可能会使调试代码更加困难,因为您不知道哪个参数导致引发异常。

例如:假设这是您的代码,但您无法阅读ExternalService的源代码,因为它是外部应用程序。您将不知道导致ExternalService中出现错误的参数是"charlie"。

    var instance = new ClassToBeInitialized
    {
        alpha = "alpha", 
        bravo = ExternalService(0),
        charlie = ExternalService(1)
    };

    private static string ExternalService(int parameter)
    {
        if (parameter == 1)
        {
            throw new Exception("The external service crashed");
        }

        return "correctStringResult";
    }

10
我来到这篇帖子,只是想查看是否有人声称相同的观点。这个话题在我所在的团队中已经讨论了几周。作为一名开发者,我确实喜欢它提供的语法糖(上面提到的其他优点对我的情况不相关),但我可以接受这个理由足够强大,不使用它(在像我这样的情况下,您不会从使用它中获得任何其他好处)。 - Veverke
1
我们还发现许多情况下,由于涉及的属性数量和外部供应商模型的复杂性,对象初始化程序语法使得调试复杂模型几乎不可能。 - user862319

16

匿名对象、LINQ查询以及有时不必要地重载构造函数仅为了传递参数的使用有其优点。


+1它还允许为这些参数进行隐式类型推断,而不必在每个地方编写new MyType() {....} 。 - cirrus
3
通过在构造函数中使用命名参数和可选参数,可以避免不必要的构造函数重载。参考链接:http://msdn.microsoft.com/en-us/library/dd264739.aspx - Jon Senchyna

1

对象初始化有三个主要优点:

  • 避免大量按键,软件程序的效率有时是通过编写特定功能所需的按键数量来衡量的。
  • 易于阅读和维护。
  • 节省时间的方法。

让我们看看它如何避免大量按键:

在 C# 3.0 之前,我们进行初始化的方式如下:

Employee emp = new Employee();
emp.Name = "Kumar";
emp.Department = "IT";
emp.Id = 101;
emp.Salary = 80000;

现在,在C#3.0之后,我们可以通过以下方式一行代码进行初始化:
Employee emp = new Employee { Name = "Kumar", Department = "IT", Id = 101, Salary = 80000 };

0

我认为这有助于提高可读性。

顺便说一下,在链接中给出的示例中,我有时倾向于为属性(FirstName和LastName)设置私有setter,但这取决于您的设计。


2
你的回答有点令人困惑。看起来你建议使用私有设置器和对象初始化语法来创建类似只读属性的功能。如果你将设置器设为私有,除非在已经可以访问这些私有设置器的位置使用它,否则无法使用对象初始化语法。 - Jon Senchyna
我同意。我应该用更好的措辞表达。回答楼主的问题,我只是认为这有助于提高可读性。我写的其余部分有点离题了。我已经编辑了文本,试图反映这一点。 - Kirby

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接