是否存在将C#7“表达体构造器”与其他活动(例如,空检查和异常抛出)结合使用的推荐或首选方法?
编写C#类时,我习惯于能够在构造函数中测试参数是否为null(并在需要时抛出异常),如下所示:-
class Person
{
private string _name;
private SomeClass _someClass;
public Person(string name, SomeClass someClass)
{
_name = name ?? throw new ArgumentNullException(nameof(name));
_someClass = someClass?? throw new ArgumentNullException(nameof(someClass));
}
}
我刚刚了解了表达体构造器,其中我的代码的简单版本可能如下所示:-
class Person
{
private string _name;
private SomeClass _someClass;
public Person(string name, SomeClass someClass)
=> (_name, _someClass) = (name, someClass);
}
上面的内容最初看起来很有吸引力,因为它有可能减少为成员变量分配参数所需的样板代码量。
但是,由于不再有构造函数主体,我似乎已经失去了包括上述空检查之类的活动的机会。
据我所知,解决此问题的唯一方法是内联代码,例如我的null-coalesce检查:-
...
public Person(string name, SomeClass someClass)
=> (_name, _someClass) =
(
name ?? throw new ArgumentNullException(nameof(name ),
someClass ?? throw new ArgumentNullException(nameof(someClass)
));
即使我试图通过空格来提高可读性,但我认为上面的内容并不像原始示例那样易于阅读-并没有真正保存任何键入内容。
问:有没有更好的方法可以解决这个问题,还是我打败了这种新型构造函数的目的? (即我应该坚持使用原始方法)
答案 0 :(得分:0)
我不会批评您的尝试。
事实是两个版本生成的代码几乎相同。
class Person
{
private string _name;
private string _someClass;
public Person(string name, string someClass)
{
_name = name ?? throw new ArgumentNullException(nameof(name));
_someClass = someClass?? throw new ArgumentNullException(nameof(someClass));
}
}
成为
class Person
{
private string _name;
private string _someClass;
public Person(string name, string someClass)
{
if (name == null)
{
throw new ArgumentNullException("name");
}
_name = name;
if (someClass == null)
{
throw new ArgumentNullException("someClass");
}
_someClass = someClass;
}
}
和
class Person
{
private string _name;
private string _someClass;
public Person(string name, string someClass)
=> (_name, _someClass) =
(
name ?? throw new ArgumentNullException(nameof(name)),
someClass ?? throw new ArgumentNullException(nameof(someClass))
);
}
成为
class Person
{
private string _name;
private string _someClass;
public Person(string name, string someClass)
{
if (name == null)
{
throw new ArgumentNullException("name");
}
if (someClass == null)
{
throw new ArgumentNullException("someClass");
}
_name = name;
_someClass = someClass;
}
}
答案 1 :(得分:0)
我认为“元组分配”样式是一种很好的简短表达方式,它表示“我的课程是从这些成员初始化的,其他都没有发生”。我看了一眼,立即知道这就是作者的意图。
一旦发生另一件事(在您的示例中进行验证),则应使用完整的构造函数。正如您所说,您可以做到这一点,但阅读起来却糟得多。
真的,我们只使用这种样式是因为我们还没有记录类型。当我们拥有这些功能时,我认为我们不会在代码中看到如此多的内容。