C#构造函数链接调用顺序

问题描述 投票:1回答:1

我有一个类可以用数据创建或使用二进制阅读器(它用于反序列化它的数据)。它使用数据进行额外的初始化,因为我不想复制该代码,所以我想链接构造函数。现在这个链接看起来像这样:

public Item(string id, int count = 1) { /*...*/ }

public Item(BinaryReader reader) : this(reader.ReadString(), reader.ReadInt32()) { /*...*/ }

这些读取调用的顺序是否确定?

澄清:我在谈论read.ReadString()reader.ReadInt32()被称为的顺序。

c# constructor constructor-chaining
1个回答
2
投票

调用具有多个参数的方法时,评估顺序的确切行为记录在C#规范Run-time evaluation of argument lists中,该规范指出:

在函数成员调用的运行时处理(动态重载决策的编译时检查)期间,参数列表的表达式或变量引用按从左到右的顺序进行计算,如下所示:

所以在你的情况下,订单将是:

  • reader.ReadString()
  • reader.ReadInt32()
  • 最后将调用另一个构造函数

现在,存在一些问题,主要与可读性和异常有关。

您询问哪个调用顺序是正确的,下一个程序员可能会遇到相同的问题。最好将其重构为一个不附带大量问题的不同解决方案。

另外,如果你传入一个null reader你会得到一个NullReferenceException而不是ArgumentNullException,即使你应该碰巧验证这个参数不是构造函数中的null,只是因为所有这些评估都会在构造函数体执行之前发生。有一些黑客可以“修复”这个,但它们比你已有的代码更糟糕。

要重构为“更好”的解决方案(我认为),您将创建一个这样的工厂方法:

public static Item Create(BinaryReader reader)
{
    if (reader == null) throw new ArgumentNullException(nameof(reader));
    // optional: handle exceptions from reader.ReadString and ReadInt32
    var s = reader.ReadString();
    var i = reader.ReadInt32();
    return new Item(s, i);
}
© www.soinside.com 2019 - 2024. All rights reserved.