对象初始值设定项和构造函数之间有什么区别?

Pet*_*ete 163 .net c# constructor object-initializer

两者之间有什么区别?何时使用"对象初始值设定项"而不是"构造函数",反之亦然?我正在使用C#,如果这很重要的话.另外,对象初始化方法是否特定于C#或.NET?

Ree*_*sey 228

对象初始化器是添加到C#3的东西,以便在使用对象时简化对象的构造.

给定0或更多参数的构造函数运行,并在调用方法获取创建对象的句柄之前用于创建和初始化对象.例如:

MyObject myObjectInstance = new MyObject(param1, param2);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,构造函数MyObject将使用值param1和运行param2.这些都用于MyObject在内存中创建新的.将返回创建的对象(使用这些参数设置)并设置为myObjectInstance.

通常,将构造函数需要所需的参数以完全设置对象被认为是一种好的做法,因此无法在无效状态下创建对象.

但是,通常可以设置"额外"属性,但不是必需的.这可以通过重载的构造函数来处理,但是导致有许多构造函数在大多数情况下不一定有用.

这会导致对象初始值设定项 - 对象初始值设定项允许您在对象构造之后设置属性或字段,但您可以通过其他任何方式使用它之前.例如:

MyObject myObjectInstance = new MyObject(param1, param2)
{
    MyProperty = someUsefulValue
};
Run Code Online (Sandbox Code Playgroud)

这与您执行此操作的行为大致相同:

MyObject myObjectInstance = new MyObject(param1, param2);
myObjectInstance.MyProperty = someUsefulValue;
Run Code Online (Sandbox Code Playgroud)

但是,在多线程环境中,对象初始值设定项的原子性可能是有益的,因为它可以防止对象处于未完全初始化的状态(有关更多详细信息,请参阅此答案) - 它可以为null,也可以像您预期的那样初始化.

此外,对象初始值设定项更易于阅读(特别是在设置多个值时),因此它们可以为构造函数提供与许多重载相同的好处,而不需要使许多重载使该类的API复杂化.

  • 我同意,但是想补充说调试对象初始化器可能很痛苦,特别是如果你有嵌套结构,因为对象初始化器被认为是一行代码(格式很好),就像我的句子一样. (37认同)
  • 你的答案很好,但**你的例子不正确**.请根据@nawfal的回答更新您的代码.你的答案有很多赞成,没有人会看到另一个,这将使很多人对对象初始化程序的工作方式有错误的理解 (6认同)
  • @Mahender实际上,使用对象初始化器时通常会有(非常非常小的)性能损失.可以编写构造函数以提高效率. (2认同)
  • 您必须权衡代码的可读性和代码的正确性。构造函数中的参数强制您设置所有变量。如果您忘记设置一个变量,编译器会抱怨。如果您在使用初始值设定项列表时忘记了变量,则直到运行时(甚至可能不会立即)您才会注意到它。此外:该字段不能是只读的,这使得意外更改成为可能,而编译器不会抱怨 (2认同)

Jar*_*Par 44

构造函数是类型上的已定义方法,它采用指定数量的参数并用于创建和初始化对象.

对象初始值设定项是在构造函数之后在对象上运行的代码,可用于将对象上的任意数量的字段简洁地设置为指定值.在调用构造函数之后会发生这些字段的设置.

如果构造函数充分设置了对象的初始状态,则可以在没有对象初始值设定项的帮助下使用构造函数.但是,对象初始值设定项必须与构造函数一起使用.语法要求构造函数的显式或隐式使用(VB.Net和C#)来创建初始对象.当构造函数没有充分初始化对象并使用一些简单的字段和/或属性集时,您将使用对象初始值设定项.


naw*_*fal 29

当你这样做

Person p = new Person { Name = "a", Age = 23 };
Run Code Online (Sandbox Code Playgroud)

这是对象初始化器基本上做的事情:

Person tmp = new Person(); //creates temp object calling default constructor
tmp.Name = "a";
tmp.Age = 23;
p = tmp;
Run Code Online (Sandbox Code Playgroud)

现在,这有利于类似行为这样.了解对象初始化程序的工作方式非常重要.

  • 我不知道可以跳过构造函数paranthesis.谢谢. (3认同)

mar*_*c_s 16

如果你的对象必须设置属性才能正常工作,一种方法是只公开一个构造函数,它需要那些必需的属性作为参数.

在这种情况下,如果不指定这些必需属性,则无法创建对象.对象初始化器无法强制执行类似的操作.

对象初始化器实际上只是缩短初始分配的"语法便利".不错,但功能上并非真正相关.

  • 确保在构造时在对象上设置基本属性的另一种方法是在返回构造对象的类上提供静态(“工厂”)方法。该工厂方法通过 *private* 构造函数构造对象。(定义多个私有构造函数可能很有用。) (2认同)