空检查运算符仍返回空值

时间:2017-12-01 13:38:44

标签: c# asp.net-core signalr signalr-hub asp.net-core-2.0

我正在尝试从我的依赖注入器获取实现类型

的所有通用服务
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 List时,我会收到错误

  

System.ArgumentNullException:'值不能为空。'

我检查了服务它不是null,但是实现类型。这怎么可能,这有些与func如何构建有关? enter image description here

修改 我如何使用Elvis操作员错误?你可以看到s有一个值。从图片。错误是从检查的类型产生的,这怎么可能?

2 个答案:

答案 0 :(得分:7)

?.运算符仅指应用它的解除引用操作。当s不仅null而且s.ImplementationType时,表达式......

s?.ImplementationType.GetTypeInfo()

......赢得不够。您需要在表达式左侧的所有位置null使用运算符:

s?.ImplementationType?.GetTypeInfo()

由于GetTypeInfo()的归还不能是null,所以写下来就足够了:

s?.ImplementationType?.GetTypeInfo().IsGenericType ?? false

一般不应将?.应用于所有解除引用,但仅在值为null并且跳过表达式的其余部分时才使用它是个好主意。如果您通常在所有情况下都应用运算符,则可能会出现错误,否则会很早发现错误。

答案 1 :(得分:4)

您必须在每个成员访问和成员调用时使用null check运算符来传播任何级别的空值,如下所示:

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