如何检查方法的返回类型是否可为空? 项目设置
<Nullable>enable</Nullable>
已激活。
一些示例(所有方法均为
Task
或 Task<T>
类型)
public sealed class Dto
{
public int Test { get; set; }
}
public sealed class Dto3
{
public int? Test { get; set; }
}
public async Task<Dto?> GetSomething()
{
// This should be found as "Nullable enabled" as the `?` is set.
}
public async Task<Dto3> GetSomething2()
{
// This should not be found as "Nullable enabled" as the `?` is missing.
}
public async Task<List<Dto>> GetSomething3()
{
// This should not be found as "Nullable enabled" as the `?` is missing
// (And the list must be initialized anyways thanks to nullable context).
}
public async Task<List<Dto?>> GetSomething3()
{
// This should not be found as "Nullable enabled" as the `?` is missing in the first generic type after `Task`.
}
我已经有了迭代搜索命名空间中的类和方法的代码,如下所示:
var assembly = Assembly.GetAssembly(typeof(ISomethingService));
if (assembly is null)
{
throw new InvalidOperationException("This should never happen");
}
var classes = assembly.GetTypes().Where(type =>
(type.Namespace == typeof(ISomethingService).Namespace || type.Namespace == typeof(ISomethingService2).Namespace) && type.IsInterface);
foreach (var @class in classes)
{
var methods = @class.GetMethods();
foreach (var method in methods)
{
foreach (var genericType in method.ReturnType.GenericTypeArguments)
{
if (IsNullable(genericType))
{
Console.WriteLine($"Return type of method {@class.Name}.{method.Name} is nullable: {genericType.Name}");
}
}
}
}
可为空检查目前是这样实现的,但没有按预期工作:
private static bool IsNullable<T>(T obj)
{
if (obj == null) return true; // obvious
Type type = typeof(T);
if (!type.IsValueType) return true; // ref-type
if (Nullable.GetUnderlyingType(type) != null) return true; // Nullable<T>
return false; // value-type
}
有没有办法达到预期的结果(例如,如果在
IsNullable
之后的第一级(泛型)设置了true
,则只有?
是Task<T>
?
在 .NET 6+ 中,您可以使用
NullabilityInfoContext
来查明字段、属性、参数或事件是否可为 null。另请参阅此答案。
ReturnParameter
,这是一个 PropertyInfo
。
bool ReturnNullableOrNullableTask(MethodInfo m) {
var context = new NullabilityInfoContext();
var returnParameter = m.ReturnParameter;
var info = context.Create(returnParameter);
if (info.ReadState == NullabilityState.Nullable) {
return true; // the return type itself is null
}
// otherwise check if it is a Task<T>
if (returnParameter.ParameterType == typeof(Task<>)) {
var firstTypeParameterInfo = info.GenericTypeArguments[0];
if (firstTypeParameterInfo.ReadState == NullabilityState.Nullable) {
return true;
}
}
return false;
}
这适用于可为空值类型和可为空引用类型。