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