C#字段初始化的顺序

问题描述 投票:3回答:2

我通过以这种方式初始化字段来创建对象:

class Example
{
    public int a;
    public int b;
}

var obj = new Example
{
    a = stream.ReadInt(),
    b = stream.ReadInt()
};

在字段“b”之前是否始终将字段“a”初始化?否则,当以不同的顺序减去流中的值时,可能会发生令人不快的错误。谢谢!

UPD:在评论中,很多人都不明白我的意思。我会澄清这个问题。这些记录在不同的(.NET,Mono等)编译器上的行为是否始终相同?

第一:

var obj = new Example
{
    a = stream.ReadInt(),
    b = stream.ReadInt()
};

第二:

var a = stream.ReadInt();
var b = stream.ReadInt();

var obj = new Example
{
    a = a,
    b = b
};
c# object-initializers
2个回答
3
投票

恕我直言,the relevant part of the C# language specification相当清楚。它可能不那么模糊,但我没有看到解释它的方法,允许无序初始化:

对象初始值设定项由一系列成员初始值设定项组成

[强调我的]。 “序列”一词必然意味着一个顺序。也许这似乎不是规范性的,但他们的例子确实如此:

可以创建Point的实例并初始化如下:

Point a = new Point { X = 0, Y = 1 };

效果与...相同

Point __a = new Point();
__a.X = 0;
__a.Y = 1;
Point a = __a;

如果编译器作者要对分配重新排序,则它们输出的程序将不符合上述示例。

更一般地说,在该部分中查看语言的其余部分是有用的,因为语言设计者竭尽全力确保该功能直观地工作,包括使用对象初始化器的嵌套赋值仅将完全形成的对象分配给父母财产。

所有这一切,真的应该没关系。如果你有一个课程,其中两个或多个属性的作业顺序会影响最终结果,那么你手上就有一个非常危险的课程。应该不惜一切代价避免这种设计,因为在任何情况下都很容易破解,即使对象初始化的编译器规则相当清楚。


0
投票

此构造称为“对象初始化器”,不应与对象/字段初始化混淆。在完全构造对象之后修改对象是很好的语法。

按照7.6.10.2中的示例 - C#5.0规范的对象初始化程序:

可以创建Point的实例并初始化如下:

Point a = new Point { X = 0, Y = 1 };

效果与...相同

Point __a = new Point();
  __a.X = 0;
  __a.Y = 1; 
Point a = __a;

规范示例隐含地涵盖了赋值的排序(这意味着以特定顺序评估RHS)以及创建对象的赋值的总顺序(即,对象不会被分配给之前的字段。正在处理的对象初始化程序)。

© www.soinside.com 2019 - 2024. All rights reserved.