空检查运算符仍然 returns 一个空值

Null Check Operator still returns a null value

我正在尝试从实现类型的依赖注入器获取所有通用服务

protected List<ServiceDescriptor> GetGenericServicesFromGenericTypeDefinition(IServiceCollection services, Type baseGenericTypeDefinition)
{
    if(false == baseGenericTypeDefinition.IsGenericTypeDefinition)
    {
        throw new Exception($"Invalid Argument {nameof(baseGenericTypeDefinition)}");
    }

    //TODO:  check the base type recursively
    var genericImplementations = services.Where(s => s?.ImplementationType.GetTypeInfo().IsGenericType ?? false)
            .ToList();
    //.... Omitted unrelated to issue
}

奇怪的是,当它尝试创建 genericImplementations 列表时,我收到一个错误

System.ArgumentNullException: 'Value cannot be null.'

我已经检查过它不是空的服务,但是实现类型是。这怎么可能,这与 func 的构造方式有什么关系吗?

编辑 我怎么用错了猫王运算符?如您所见,s 具有一个值。从图片。错误是从检查的类型生成的,这怎么可能?

您必须在每个成员访问和成员调用中使用 null 检查运算符来从任何级别传播 null,如下所示:

var genericImplementations = services.Where(s => s?.ImplementationType?.GetTypeInfo()?.IsGenericType ?? false).ToList();

?. 运算符仅引用它所应用的取消引用操作。当不仅s可以是null,而且s.ImplementationType,表达式...

s?.ImplementationType.GetTypeInfo()

...还不够。您需要在表达式 左侧 可以是 null:

的所有地方使用运算符
s?.ImplementationType?.GetTypeInfo()

由于GetTypeInfo()的return不能是null,写成:

就可以了
s?.ImplementationType?.GetTypeInfo().IsGenericType ?? false

最好不要将 ?. 通常应用于所有取消引用,而是仅在值可能为 null 时才使用它并且跳过表达式的其余部分就可以了。如果您在所有情况下都普遍应用运算符,则错误可能会失败,否则会及早发现。