使用对象初始化语法的操作顺序

38

使用对象初始化器语法设置属性的顺序是否会以完全相同的顺序执行?

例如,如果我这样做:

var s = new Person { FirstName = "Micah",
                     LastName = "Martin",
                     IsLoaded = true
                   }

每个属性都会按照相同的顺序设置吗?

1个回答

56

可以。

很抱歉被打断了(我偶尔必须要做些工作)。规范没有明确说明,但在7.6.10.2节中它表达得相当清楚:(注意这里使用的是“序列”而不是“集合”一词。我个人认为这很重要,因为序列是有序的。)


对象初始化程序由成员初始化程序序列组成,由{和}令牌括起来,并用逗号分隔。

以下类表示具有两个坐标的点:

public class Point
{
    int x, y;
    public int X { get { return x; } set { x = value; } }
    public int Y { get { return y; } set { y = value; } }
}

可以按照以下方式创建和初始化Point的实例:

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

其效果与

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

其中__a是一个在其他情况下不可见且无法访问的临时变量。


编辑:我收到了Mads Torgersen的回复,他基本上表示现在可以做的任何事情都会保留顺序。未来可能会有一些奇怪的情况,在这些情况下你正在进行一些设置属性/字段的操作,但这将取决于语言的发展方向。

值得指出的是这里实际上有很多步骤-有参数(即RHS部分)评估执行的顺序以及赋值执行的顺序。例如:

new Foo
{
    A = X,
    B = Y
}

在保持实际属性执行顺序(A和B)的情况下,以下所有顺序都是可能的:

  • 评估X,分配给A,评估Y,分配给B
  • 评估X,评估Y,分配给A,分配给B
  • 评估Y,评估X,分配给A,分配给B

我相信第一个选项是实际采取的选项,但这只是为了说明这里面有更多的东西需要注意。

我也非常警惕编写依赖于此的代码...


1
我最大的担忧是分配按照我列出的顺序进行。我不太关心右侧的评估顺序,而是实际左侧分配顺序。 - Micah
3
嗯,在我的情况下,我的担忧正好相反。对我来说,分配顺序并不重要,因为我只需要初始化对象/结构。但是,评估顺序很重要,因为我使用BinaryReader,并且每个字段都由ReadSingle()调用设置。如果不能保证顺序,最好完全避免对象初始化程序。安全第一。如果没有得到适当的规定,这种语法糖就毫无用处^^。是否有任何已记录的情况,其中未保留评估顺序? - Bunny83
2
@Bunny83:据我所知,我非常有信心顺序*被保留了,并且这是规范的意图-只是没有像它应该的那样明确。 - Jon Skeet
@JonSkeet 我想知道语言中添加“init”是否对属性的执行顺序产生了影响。其中一些现在调用“set”,而其他一些则调用“init”。我猜大多数情况下不会有变化-- - sjb-sjb
我在这里找到了它:https://dev59.com/EMLra4cB1Zd3GeqPOacA - sjb-sjb
显示剩余4条评论

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