我们可以让这个单行更简洁吗?
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(或 EcmaScript 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 true
或 false
函数而不是抛出异常,那么它就变得非常简单明了:
public async Task<bool> EnsureAuthenticated()
{
return IsAuthenticated || (await Authenticate()).IsSuccess;
}
我想知道是否可以像 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(或 EcmaScript 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 true
或 false
函数而不是抛出异常,那么它就变得非常简单明了:
public async Task<bool> EnsureAuthenticated()
{
return IsAuthenticated || (await Authenticate()).IsSuccess;
}