如果方法 Returns 完全指定 NotNull
Specify NotNull If Method Returns At All
我正在使用 C# 8 中新的可空引用类型,我想知道如果方法 returns 是否可以指示传入的参数不为空。
我找到了 [NotNullIf]
和 [DoesNotReturnIf]
,但它们似乎分别触发了方法的 return 值和特定的 bool
参数。
这是我目前拥有的:
public static bool RaiseIfNull([NotNullWhen(true)] object? thing) => RaiseIf(() => thing is null);
public static bool RaiseIf(Func<bool> predicate)
{
if (predicate()) throw new HttpException(400);
return true;
}
这看起来不错,但是当我调用它时 - 我仍然看到警告。 (我也试过 RaiseIfNull([NotNullIfNotNull("thing")] object? thing)
但没用。)
[HttpPost("{id}")]
public async Task Etc(string id, [FromBody] Dto data)
{
HttpException.RaiseIfNull(data?.property);
await DoEtc(id, data.property)); // warning here
}
我是不是遗漏了什么明显的东西?
使用正常的 null 检查
首先,RaiseIfNull
所提供的不超过:
var value=data?.property ?? new HttpException(400);
编译器可以识别的。 RaiseIfNull
另一方面隐藏了实际发生的事情。此代码不会产生警告:
class D
{
public string? property{get;set;}
}
D? data=null;
var value=data?.property ?? throw new HttpException(400);
Console.WriteLine(value.Length);
无条件Post-条件和泛型
也就是说,要使用的正确参数是 NotNull
- 在方法执行后,即使类型本身可以为 null,参数也不为 null。该属性可以应用于:
- 参数
- 属性
- 字段和
- Return 值
这些方法也可以是通用的,以避免将结构装箱到对象中。为此,我们需要指定类型是 class 还是结构,因为生成的具体类型非常不同——string?
仍然是字符串,而 int?
是 Nullable<int>
:
public static bool RaiseIfNull<T>([NotNull] T? thing)
where T:class
=> RaiseIf(() => thing is null);
public static bool RaiseIfNull<T>([NotNull] T? thing)
where T:struct
=> RaiseIf(() => thing is null);
鉴于这些方法,以下代码也不会生成警告:
D? data=null;
RaiseIfNull(data?.property);
Console.WriteLine(data.property.Length);
最后,我们可以去掉 return 值:
public static void RaiseIfNull<T>([NotNull] T? thing)
where T:class
=> RaiseIf(() => thing is null);
public static void RaiseIfNull<T>([NotNull] T? thing)
where T:struct
=> RaiseIf(() => thing is null);
我正在使用 C# 8 中新的可空引用类型,我想知道如果方法 returns 是否可以指示传入的参数不为空。
我找到了 [NotNullIf]
和 [DoesNotReturnIf]
,但它们似乎分别触发了方法的 return 值和特定的 bool
参数。
这是我目前拥有的:
public static bool RaiseIfNull([NotNullWhen(true)] object? thing) => RaiseIf(() => thing is null);
public static bool RaiseIf(Func<bool> predicate)
{
if (predicate()) throw new HttpException(400);
return true;
}
这看起来不错,但是当我调用它时 - 我仍然看到警告。 (我也试过 RaiseIfNull([NotNullIfNotNull("thing")] object? thing)
但没用。)
[HttpPost("{id}")]
public async Task Etc(string id, [FromBody] Dto data)
{
HttpException.RaiseIfNull(data?.property);
await DoEtc(id, data.property)); // warning here
}
我是不是遗漏了什么明显的东西?
使用正常的 null 检查
首先,RaiseIfNull
所提供的不超过:
var value=data?.property ?? new HttpException(400);
编译器可以识别的。 RaiseIfNull
另一方面隐藏了实际发生的事情。此代码不会产生警告:
class D
{
public string? property{get;set;}
}
D? data=null;
var value=data?.property ?? throw new HttpException(400);
Console.WriteLine(value.Length);
无条件Post-条件和泛型
也就是说,要使用的正确参数是 NotNull
- 在方法执行后,即使类型本身可以为 null,参数也不为 null。该属性可以应用于:
- 参数
- 属性
- 字段和
- Return 值
这些方法也可以是通用的,以避免将结构装箱到对象中。为此,我们需要指定类型是 class 还是结构,因为生成的具体类型非常不同——string?
仍然是字符串,而 int?
是 Nullable<int>
:
public static bool RaiseIfNull<T>([NotNull] T? thing)
where T:class
=> RaiseIf(() => thing is null);
public static bool RaiseIfNull<T>([NotNull] T? thing)
where T:struct
=> RaiseIf(() => thing is null);
鉴于这些方法,以下代码也不会生成警告:
D? data=null;
RaiseIfNull(data?.property);
Console.WriteLine(data.property.Length);
最后,我们可以去掉 return 值:
public static void RaiseIfNull<T>([NotNull] T? thing)
where T:class
=> RaiseIf(() => thing is null);
public static void RaiseIfNull<T>([NotNull] T? thing)
where T:struct
=> RaiseIf(() => thing is null);