c#构造函数链接呼叫顺序



我有一个可以用数据或二进制读取器创建的类(它用于对其数据进行挑选(。它可以对数据进行其他初始化,并且由于我不想复制该代码,所以我想链接构造函数。现在,这个封锁看起来像这样:

public Item(string id, int count = 1) { /*...*/ }
public Item(BinaryReader reader) : this(reader.ReadString(), reader.ReadInt32()) { /*...*/ }

这些读取的呼叫是确定性的吗?

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

评估顺序的确切行为是在C#规范列表中记录了具有多个参数的方法,该参数列表的运行时间评估:

在函数成员调用的运行时处理过程中(动态过载分辨率的编译时间检查(,从左到右评估了参数列表的表达式或参数列表的变量引用。,如下:

因此,在您的情况下,订单将是:

  • reader.ReadString()
  • reader.ReadInt32()
  • 最后,另一个构造函数将被称为

现在,有两个问题,主要与可读性和例外有关。

询问哪个呼叫顺序是正确的事实,下一个程序员可能会有相同的问题。最好将其重构为另一种解决方案,而这些解决方案不会带来很多问题。

此外,如果您通过 null reader,即使您应该碰巧验证此参数不是构造函数内部的 null,也将获得 NullReferenceException而不是 ArgumentNullException执行。 hacks 要"修复"此问题,但它们比您已经拥有的代码差。

要重构为"更好"解决方案(我的意见(,您将创建这样的工厂方法:

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);
}

最新更新