我们可以让这个单行更简洁吗?

Could we make this one-liner any more concise?

我想知道是否可以像 JavaScript 一样使用 C# 来简化代码。我尝试用更少的行编写以下代码:

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(或 E​​cmaScript 2017,如果考虑 async/await)中的等效代码相比,代码仍然太多。但我的问题主要是关于 lambda 部分 ((Func<bool>)(() => { throw new AuthenticationException(); }))().

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

首先,C# 7 确实允许你做你描述的事情,允许在条件的第二个或第三个操作数中使用throw运算符(?:)。所以你可以这样写你的方法:

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

但是,看起来您正试图将可读代码变成等同于糟糕(几乎不可读)的 JavaScript 代码,并且由于强制使用该编码风格而在顶部添加了一些额外的不可读性C#.

你可以这样做;很简单:

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

您可以使用 DeMorgan 定律来消除其中一个 !

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

但是仔细想想,return这个值如果只有一个可能的值就很没意义了,所以你可以去掉它。两个可能的结果然后变成 (1) throw or (2) not throw 而不是 (1) throw or (2) return true:

public async Task EnsureAuthenticated()
{
    if (!(IsAuthenticated || (await Authenticate()).IsSuccess))
    {
        throw new AuthenticationException();
    }
}

当然,如果您决定使用 returning truefalse 函数而不是抛出异常,那么它就变得非常简单明了:

public async Task<bool> EnsureAuthenticated()
{
    return IsAuthenticated || (await Authenticate()).IsSuccess;
}