【问题标题】:Order of operations using Object Initializer Syntax使用对象初始化器语法的操作顺序
【发布时间】:2009-01-30 14:14:56
【问题描述】:

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

例如,如果我这样做:

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

每个属性的设置顺序是否相同?

【问题讨论】:

    标签: .net syntax object-initializers


    【解决方案1】:

    是的。

    抱歉被打断了(实际上我必须经常做一些工作)。规范没有明确说出来,但它在第 7.6.10.2 节中清楚地说明了 IMO:


    对象初始值设定项由一系列成员初始值设定项组成,由 { 和 } 标记括起来并用逗号分隔。

    (注意这里的“序列”一词,而不是“集合”。我个人认为这很重要,因为序列是有序的。)

    下面的类表示一个有两个坐标的点:

    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

    我相信第一个选项是实际采用的选项,但这只是为了证明它比表面上看到的更多。

    我也会非常对实际编写依赖于此的代码保持警惕......

    【讨论】:

    • 我最担心的是分配按照我列出它们的顺序发生。我并不关心右侧的评估顺序,而是关心实际的左侧分配顺序。
    • 嗯。就我而言,我的担忧是相反的。分配顺序对我来说无关紧要,因为我只需要初始化对象/结构。但是,评估顺序很重要,因为我使用 BinaryReader 并且每个字段都由 ReadSingle() 调用设置。如果不能保证顺序,我最好完全避免使用对象初始化器。安全总比后悔好。如果没有正确指定,这种语法糖是毫无用处的^^。实际上是否有任何记录在案的情况下没有保留评估顺序?
    • @Bunny83:我不知道,而且我非常有信心订单被保留,这就是规范的意图 - 它只是没有尽可能明确。
    猜你喜欢
    • 2013-06-27
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多