我正在使用 ReSharper 2024.2,但我仍然收到建议,认为我不应该使用以下代码:
public async Task<T> GetQueryAsync<T>(string query, bool isToBeValidated = true) where T : IEndPointResponse
{
ArgumentNullException.ThrowIfNullOrEmpty(query);
ArgumentNullException.ThrowIfNullOrWhiteSpace(query);
ArgumentNullException.ThrowIfNull(Logger);
相反,它建议我使用
public async Task<T> GetQueryAsync<T>(string query, bool isToBeValidated = true) where T : IEndPointResponse
{
ArgumentException.ThrowIfNullOrEmpty(query);
ArgumentException.ThrowIfNullOrWhiteSpace(query);
ArgumentNullException.ThrowIfNull(Logger);
或者
public async Task<T> GetQueryAsync<T>(string query, bool isToBeValidated = true) where T : IEndPointResponse
{
if (string.IsNullOrEmpty(query) || string.IsNullOrWhiteSpace(query)) throw new ArgumentNullException(nameof(query));
ArgumentNullException.ThrowIfNull(Logger);
这表明我正在使用 ArgumentException 的基本方法,因为 ArgumentNullException 派生自它,但这很糟糕,因为我所有的单元测试都期望 ArgumentNullException - 事实上,这可以说是更合适的抛出异常。 所有单元测试样板测试都会自动测试 ArgumentNullException,但在第一个代码示例中,ReSharper 中默认情况下坚持前 2 行不正确,但第三行则不然 (ArgumentNullException.ThrowIfNull(Logger))。
这背后的理由是什么? 这是一个错误,还是我应该总是抛出 ArgumentException? 只是寻找一些想法,因为在我使用 C# 的 16 年中,几乎都是使用 ReSharper,我从未遇到过这个问题。
这是正确的建议。
如果您阅读ArgumentException.ThrowIfNullOrEmpty
上的
docs,则写道:
例外情况
参数为空。ArgumentNullException
参数为空。ArgumentException
因此,当参数为
null
时,它仍然会抛出 ArgumentNullException
。
所以建议是有效的。
这背后的理由是什么?这是一个错误,还是我应该总是抛出 ArgumentException?
ArgumentException.ThrowIfNull
会抛出 ArgumentNullException
。它只是ArgumentException
上的静态方法。想象一下这些方法实际上是这样写的:
public class UtilityClass
{
public static void ThrowIfNullOrEmpty(string? argument,
string? paramName = default)
{
if (argument is null)
{
throw new ArgumentNullException(paramName);
}
}
}
public class DerivedUtilityClass : UtilityClass
{
}
现在想象一下你的代码是这样写的:
public async Task<T> GetQueryAsync<T>(string query, bool isToBeValidated = true) where T : IEndPointResponse
{
DerivedUtilityClass.ThrowIfNullOrEmpty(query);
...
}
ReSharper 有效地建议您的代码应编写为:
```csharp
public async Task<T> GetQueryAsync<T>(string query, bool isToBeValidated = true) where T : IEndPointResponse
{
// Note: UtilityClass not DerivedUtilityClass
UtilityClass.ThrowIfNullOrEmpty(query);
...
}
调用方法的类型并不能决定抛出的异常。