我有一个可以用数据或二进制阅读器创建的类(它用于反序列化它的数据)。它使用数据进行额外的初始化,因为我不想复制该代码,所以我想链接构造函数。现在这个链接看起来像这样:
public Item(string id, int count = 1) { /*...*/ }
public Item(BinaryReader reader) : this(reader.ReadString(), reader.ReadInt32()) { /*...*/ }
这些读取调用的顺序是否具有确定性?
澄清:我在谈论调用read.ReadString()
和reader.ReadInt32()
的顺序。
答案 0 :(得分: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);
}