如何判断方法的返回类型是否可以为空? 项目设置<Nullable>enable</Nullable>是活动的.

一些示例(所有方法都是类型TaskTask<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
}

有没有办法达到想要的结果(例如,如果在Task<T>之后的第一级(泛型)上设置了?,则只有IsNullabletrue)?

推荐答案

在.NET6+中,您可以使用NullabilityInfoContext来确定一个字段、属性、参数或事件是否可以为空.另请参见this answer.

在您的例子中,您希望获得方法的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.IsGenericType && returnParameter.ParameterType.GetGenericTypeDefinition() == typeof(Task<>)) {
        var firstTypeParameterInfo = info.GenericTypeArguments[0];
        if (firstTypeParameterInfo.ReadState == NullabilityState.Nullable) {
            return true;
        }
    }
    return false;
}

这适用于可为空的值类型和可为空的引用类型.

Csharp相关问答推荐

使用WinSCP和C#将文件从STP服务器上的一个目录复制到另一个目录

如何使用Microsoft Curve API从搜索的文件中获取内容(文本)?

在实际上是List T的 IESEARCH上多次调用First()是否不好?

如何注销Microsoft帐户?

为什么SignalR在每个Blazor服务器应用程序启动时最多启动8个服务器?

不带身份的Blazor服务器.Net 8 Cookie身份验证

只有第一个LINQ.Count()语句有效

如何从ASP.NET核心MVC视图和Blazor传递数据

从ASP.NET Core中的枚举字段填充 Select 选项时,将默认的第一个选项添加为 Select 元素

当前的文化决定了错误的文化

如何使用MoQ模拟Resources GroupCollection?

C# CompareTo()和Compare()可以返回除-1和1以外的整数吗?

该函数不能检测两条曲线的交点

如何返回具有泛型的类?

如何从Entity Framework Core中填充ListIInterface

C#LINQ延迟执行和嵌套方法

发布.NET 8 Blazor WebAssembly独立应用程序以进行静态站点部署

如何使用EPPlus C#在单个单元格中可视化显示多行文字

当我手动停止和关闭系统并打开时,Windows服务未启动

获取应用程序版本信息时出现奇怪信息