这两者之间有什么区别?什么时候你会使用“对象初始化器”而不是“构造器”,反之亦然?如果有关系的话,我正在使用C#。另外,对象初始化器方法是C#还是.NET特有的?
m4pnthwp1#
对象初始化器是添加到C#3中的东西,目的是在使用对象时简化对象的构造。构造函数在给定0个或多个参数的情况下运行,用于在调用方法获得所创建对象的句柄之前创建和初始化对象。例如:
MyObject myObjectInstance = new MyObject(param1, param2);
在本例中,MyObject的构造函数将使用值param1和param2运行,这两个值都用于在内存中创建新的MyObject,返回创建的对象(使用这些参数设置),并将其设置为myObjectInstance。一般来说,让构造函数需要所需的参数来完全设置对象被认为是一种很好的做法,这样就不可能创建处于无效状态的对象。然而,通常有一些“额外的”属性可以设置,但不是必需的。这可以通过重载构造函数来处理,但会导致大量构造函数在大多数情况下不一定有用。这就产生了对象初始化器--对象初始化器允许你在构造对象 * 之后 *,但在 * 之前 *,在你可以使用它之前 *,在你的对象上设置属性或字段。
MyObject
param1
param2
myObjectInstance
MyObject myObjectInstance = new MyObject(param1, param2) { MyProperty = someUsefulValue };
这将与执行以下操作时的行为大致相同:
MyObject myObjectInstance = new MyObject(param1, param2); myObjectInstance.MyProperty = someUsefulValue;
然而,在 * 多线程 * 环境中,对象初始化器的原子性可能是有益的,因为它可以防止对象处于未完全初始化的状态(更多细节请参见this answer)-它要么为null,要么按照您的预期进行初始化。此外,对象初始化式更易于读取(尤其是在设置多个值时),因此它们与构造函数上的许多重载给予相同的好处,而无需使用许多重载来使该类的API复杂化。
nnsrf1az2#
构造函数是类型上的已定义方法,它接受指定数量的参数,并用于创建和初始化对象。对象初始化器是在构造函数之后在对象上运行的代码,可用于将对象上任意数量的字段简洁地设置为指定值。这些字段的设置发生在构造函数被调用之后。如果构造函数充分地设置了对象的初始状态,那么你可以在没有对象初始化器的帮助下使用构造函数。然而,对象初始化器必须与构造函数一起使用。语法要求显式或隐式使用(VB .NET和C#)的构造函数来创建初始对象。当构造函数不能充分初始化对象以供使用时,您可以使用对象初始化器,而一些简单的字段和/或属性集可以。
slwdgvem3#
当你这样做
Person p = new Person { Name = "a", Age = 23 };
这就是对象初始化器本质上要做的:
Person tmp = new Person(); //creates temp object calling default constructor tmp.Name = "a"; tmp.Age = 23; p = tmp;
现在,这有助于this这样的行为,了解对象初始化器是如何工作的非常重要。
8yparm6h4#
如果你的对象有一些属性必须设置才能正常工作,一种方法是只公开一个构造函数,这个构造函数需要那些强制属性作为参数。在这种情况下,你不能创建你的对象而不指定那些强制性的属性。类似的东西不能被对象初始化器强制执行。对象初始化器实际上只是缩短初始赋值的“语法便利”。很好,但在功能上不是很相关。马克
vtwuwzda5#
构造函数是一个接受参数并返回一个类的新示例的方法。它可能包含初始化逻辑。下面你可以看到一个构造函数的例子。
public class Foo { private SomeClass s; public Foo(string s) { s = new SomeClass(s); } }
现在考虑下面的例子:
public class Foo { public SomeClass s { get; set; } public Foo() {} }
使用对象初始值设定项可以获得与第一个示例相同的结果,前提是您可以使用以下代码访问SomeClass:
new Foo() { s = new SomeClass(someString) }
正如你所看到的,对象初始化器允许你在构造的同时为公共字段和公共(可设置的)属性指定值,当构造函数不提供任何重载来初始化某些字段时,这一点特别有用。请注意,对象初始化器只是语法上的糖衣,编译后的对象初始化器与赋值序列没有什么不同。
mlnl4t2r6#
对象初始化器可以用来初始化一些小的集合,这些集合可以在初始程序创建阶段用于测试目的。代码示例如下:
class Program { static void Main(string[] args) { List<OrderLine> ordersLines = new List<OrderLine>() { new OrderLine {Platform = "AmazonUK", OrderId = "200-2255555-3000012", ItemTitle = "Test product 1"}, new OrderLine {Platform = "AmazonUK", OrderId = "200-2255555-3000013", ItemTitle = "Test product 2"}, new OrderLine {Platform = "AmazonUK", OrderId = "200-2255555-3000013", ItemTitle = "Test product 3"} }; } } class OrderLine { public string Platform { get; set; } public string OrderId { get; set; } public string ItemTitle { get; set; } }
下面是捕获。在上面的代码示例中没有包含任何构造函数,它可以正常工作,但如果一些带参数的构造函数将包含在OrderLine类中,例如:
public OrderLine(string platform, string orderId, string itemTitle) { Platform = platform; OrderId = orderId; ItemTitle = itemTitle; }
编译器将显示错误-没有与所需形参对应的给定参数....可以通过在OrderLine类中包含不带参数的显式默认构造函数来修复:
public OrderLine() {}
zour9fqk7#
对象初始值设定项在LINQ查询表达式中特别有用。查询表达式经常使用匿名类型,这些类型只能使用对象初始值设定项初始化,如下面的代码示例所示:'
var orderLineReceiver = new { ReceiverName = "Name Surname", ReceiverAddress = "Some address" };
更多信息-Object and collection initializers
gmxoilav8#
现在,多年以后,我重新考虑使用构造函数而不是对象初始化器。我一直喜欢对象初始化器,因为它们快速而简单。选择你想要设置的字段,然后设置它们,你就完成了。但是沿着了nullable context,你必须指定哪些属性可以为空,哪些不可以。如果你忽略使用构造函数,而使用对象初始化器,编译器将不能保证你的对象实际上是完整的(没有空属性,实际上应该是非空的)。
nullable context
8条答案
按热度按时间m4pnthwp1#
对象初始化器是添加到C#3中的东西,目的是在使用对象时简化对象的构造。
构造函数在给定0个或多个参数的情况下运行,用于在调用方法获得所创建对象的句柄之前创建和初始化对象。例如:
在本例中,
MyObject
的构造函数将使用值param1
和param2
运行,这两个值都用于在内存中创建新的MyObject
,返回创建的对象(使用这些参数设置),并将其设置为myObjectInstance
。一般来说,让构造函数需要所需的参数来完全设置对象被认为是一种很好的做法,这样就不可能创建处于无效状态的对象。
然而,通常有一些“额外的”属性可以设置,但不是必需的。这可以通过重载构造函数来处理,但会导致大量构造函数在大多数情况下不一定有用。
这就产生了对象初始化器--对象初始化器允许你在构造对象 * 之后 *,但在 * 之前 *,在你可以使用它之前 *,在你的对象上设置属性或字段。
这将与执行以下操作时的行为大致相同:
然而,在 * 多线程 * 环境中,对象初始化器的原子性可能是有益的,因为它可以防止对象处于未完全初始化的状态(更多细节请参见this answer)-它要么为null,要么按照您的预期进行初始化。
此外,对象初始化式更易于读取(尤其是在设置多个值时),因此它们与构造函数上的许多重载给予相同的好处,而无需使用许多重载来使该类的API复杂化。
nnsrf1az2#
构造函数是类型上的已定义方法,它接受指定数量的参数,并用于创建和初始化对象。
对象初始化器是在构造函数之后在对象上运行的代码,可用于将对象上任意数量的字段简洁地设置为指定值。这些字段的设置发生在构造函数被调用之后。
如果构造函数充分地设置了对象的初始状态,那么你可以在没有对象初始化器的帮助下使用构造函数。然而,对象初始化器必须与构造函数一起使用。语法要求显式或隐式使用(VB .NET和C#)的构造函数来创建初始对象。当构造函数不能充分初始化对象以供使用时,您可以使用对象初始化器,而一些简单的字段和/或属性集可以。
slwdgvem3#
当你这样做
这就是对象初始化器本质上要做的:
现在,这有助于this这样的行为,了解对象初始化器是如何工作的非常重要。
8yparm6h4#
如果你的对象有一些属性必须设置才能正常工作,一种方法是只公开一个构造函数,这个构造函数需要那些强制属性作为参数。
在这种情况下,你不能创建你的对象而不指定那些强制性的属性。类似的东西不能被对象初始化器强制执行。
对象初始化器实际上只是缩短初始赋值的“语法便利”。很好,但在功能上不是很相关。
马克
vtwuwzda5#
构造函数是一个接受参数并返回一个类的新示例的方法。它可能包含初始化逻辑。下面你可以看到一个构造函数的例子。
现在考虑下面的例子:
使用对象初始值设定项可以获得与第一个示例相同的结果,前提是您可以使用以下代码访问SomeClass:
正如你所看到的,对象初始化器允许你在构造的同时为公共字段和公共(可设置的)属性指定值,当构造函数不提供任何重载来初始化某些字段时,这一点特别有用。请注意,对象初始化器只是语法上的糖衣,编译后的对象初始化器与赋值序列没有什么不同。
mlnl4t2r6#
对象初始化器可以用来初始化一些小的集合,这些集合可以在初始程序创建阶段用于测试目的。代码示例如下:
下面是捕获。在上面的代码示例中没有包含任何构造函数,它可以正常工作,但如果一些带参数的构造函数将包含在OrderLine类中,例如:
编译器将显示错误-没有与所需形参对应的给定参数....可以通过在OrderLine类中包含不带参数的显式默认构造函数来修复:
zour9fqk7#
对象初始值设定项在LINQ查询表达式中特别有用。查询表达式经常使用匿名类型,这些类型只能使用对象初始值设定项初始化,如下面的代码示例所示:'
更多信息-Object and collection initializers
gmxoilav8#
现在,多年以后,我重新考虑使用构造函数而不是对象初始化器。我一直喜欢对象初始化器,因为它们快速而简单。选择你想要设置的字段,然后设置它们,你就完成了。
但是沿着了
nullable context
,你必须指定哪些属性可以为空,哪些不可以。如果你忽略使用构造函数,而使用对象初始化器,编译器将不能保证你的对象实际上是完整的(没有空属性,实际上应该是非空的)。