将 expression-bodied 与 throw 混合用于多个参数

Mixing expression-bodied with throw for multiple parameters

这可能是一件简单的事情。但如果可能的话我无法解决这个问题。

因为我们可以将表达式体成员应用于构造函数,并且因为表达式体成员可以使用抛出表达式,所以我们可以简化以下代码

public class Foo
{
    public string ProA { get; set; }
    public Foo(string proa)
    {
        if (proa == null)
        {
            throw new ArgumentNullException("Invalid proa value");
        }
        ProA = proa;
    }
}

以上代码可以简化为:

public class Foo
{
    public string ProA { get; set; }
    public Foo(string proa) => ProA = proa ?? 
        throw new ArgumentNullException("Invalid proa value");
}

问题:在我的例子中,我有多个参数(在参数化构造函数中)在构造时进行解析,如果有人可以帮助我简化以下操作,那将非常有帮助在构造函数的表达式主体成员的帮助下编写代码,并在 null

的情况下抛出表达式
public class Bar
{
    public string ProA { get; set; }
    public string ProB { get; set; }
    public Bar(string proa, string prob)
    {
        if (proa == null)
            throw new ArgumentNullException("Invalid proa value");
        else if (prob == null)
            throw new ArgumentNullException("Invalid prob value");

        ProA = proa;
        ProB = prob;
    }
}

[it] would be very helpful if someone can help me to simplify following code with the help of expression-bodied members to constructors along with throwing expressions in case of null

"Simplify" 通常是旁观者的眼睛,我认为这里尤其如此。我还认为您混淆了两个不同的概念:表达式中的 throw 和 lambda 表达式方法实现。

如果我们只关注前者,您的构造函数可以大大简化(在我看来)只需更改表达式并删除显式 if 语句:

public class Bar
{
    public string ProA { get; set; }
    public string ProB { get; set; }
    public Bar(string proa, string prob)
    {
        ProA = proa ?? throw new ArgumentNullException("Invalid proa value");
        ProB = prob ?? throw new ArgumentNullException("Invalid prob value");
    }
}

请务必注意,逻辑流程中存在细微变化。 IE。参数验证仅在每个 属性 分配时完成,而不是在任何 属性 分配之前完成。但当然在这样的 class 中,这完全无关紧要。

可以用 lambda 表达式方法做一些类似的事情,但有相同的警告(即赋值和验证混合在一起):

public class Bar
{
    public string ProA { get; set; }
    public string ProB { get; set; }
    public Bar(string proa, string prob) : this(prob) => ProA = proa ?? throw new ArgumentNullException("Invalid proa value");
    private Bar(string prob) => ProB = prob ?? throw new ArgumentNullException("Invalid prob value");
}

换句话说,为每个要分配的参数添加一个新的构造函数,为该构造函数提供一个 lambda 表达式来分配该参数,并让构造函数将剩余参数的分配委托给下一个构造函数(更多parameters/properties,你可以看到参数列表每次调用都会缩短一个参数。

我个人认为这并不是一个真正的改进。是的,代码更紧凑。但我不太确定它实际上更 可读性 。而且在重要的意义上,"simple" 和 "readable" 是相同的,或者至少是非常密切相关的。

Question: In my case, I have more than one parameter (in a parameterised constructor ) to parse while construction and would be very helpful if someone can help me to simplify following code with the help of expression-bodied members to constructors along with throwing expressions in case of null

Expression-bodied 成员在 C# 7.0 中得到扩展,现在包括将它们与构造函数一起使用。该方法由一个 单个表达式组成,该表达式 return 是一个类型与该方法的 return 类型匹配的值,或者,对于 return 无效的方法,该表达式执行某些操作

让我们来看看您的第一个简化代码块...

public class Foo
{
    public string ProA { get; set; }
    public Foo(string proa) => ProA = proa ?? 
        throw new ArgumentNullException("Invalid proa value");
}

这里用expression-body就好了,只有one expression,所以有效

public Foo(string proa) => ProA = proa ?? 
            throw new ArgumentNullException("Invalid proa value");

当您有多个参数时就会出现问题,需要处理多个参数而不是 body 声明,表达式主体应该派上用场并起作用。

这是执行此操作的一种方法,同时使其有效。

public Bar(string proa, string prob) => 
            (ProA, ProB) = (proa ?? throw new ArgumentNullException("Invalid proa value"),
            prob ?? throw new ArgumentNullException("Invalid prob value"));

本质上,我在这里所做的是创建一个 ValueTuple Struct as well as deconstructing,它让您只需一次操作即可解包元组中的所有项目。

可以 做的另一个选择,但更多的工作是在 class 中调用例程以在构建时设置 class。事实证明,走这条路比仅处理常规 body.

中的更改要麻烦

参考文献:

Expression-bodied Members