我们能不能简化这种单行程?

时间:2017-03-25 19:16:48

标签: javascript c# .net lambda roslyn

我想知道我是否可以使用C#更像JavaScript来快捷代码。我尝试用更少的代码制作以下代码:

public async Task<bool> EnsureAuthenticated()
{
    if (!IsAuthenticated)
    {
        if (!(await Authenticate()).IsSuccess)
        {
            throw new AuthenticationException();
        };
    }
    return true;
}

哪个成了:

public async Task<bool> EnsureAuthenticated()
{
    Func<bool> throwException = () => { throw new AuthenticationException(); };
    return IsAuthenticated || (await Authenticate()).IsSuccess || throwException();
}

最接近单线的是:

public async Task<bool> EnsureAuthenticated()
{
    return IsAuthenticated || (await Authenticate()).IsSuccess ||
    ((Func<bool>)(() => { throw new AuthenticationException(); }))();
}

与JavaScript中的等效代码相比,代码仍然太多(如果考虑async / await,则为EcmaScript 2017)。但我的问题主要是关于lambda部分((Func<bool>)(() => { throw new AuthenticationException(); }))()

在C#或C#vNext中有没有更简洁的方法呢?

1 个答案:

答案 0 :(得分:5)

首先,C#7 允许您执行类似于您所描述的操作,允许在条件运算符的第2或第3个操作数中使用throw({{1 }})。所以你可以这样编写你的方法:

?:

然而,看起来您正试图将可读代码转换为相当于糟糕(几乎不可读)的JavaScript代码,并且由于强制将编码风格强加到C#中而增加了一些额外的不可读性。

你可以这样做;它很简单:

public async Task<bool> EnsureAuthenticated()
{
    return (IsAuthenticated || (await Authenticate()).IsSuccess)
        ? true
        : throw new AuthenticationException();
}

您可以使用DeMorgan定律来消除其中一个public async Task<bool> EnsureAuthenticated() { if (!IsAuthenticated && !(await Authenticate()).IsSuccess) { throw new AuthenticationException(); } return true; } s:

!

但是当你考虑它时,如果返回值只有一个可能的值,那么返回值就毫无意义,所以你可以消除它。然后两个可能的结果变成(1)抛出或(2)不抛出而不抛出(1)抛出或(2)返回public async Task<bool> EnsureAuthenticated() { if (!(IsAuthenticated || (await Authenticate()).IsSuccess)) { throw new AuthenticationException(); } return true; }

true

当然,如果您决定使用返回public async Task EnsureAuthenticated() { if (!(IsAuthenticated || (await Authenticate()).IsSuccess)) { throw new AuthenticationException(); } } true的函数而不是抛出异常,那么它会变得非常简单明了:

false