猫王运算符 ?.奇怪的是在明显的情况下无法编译

Elvis operator ?. strangely doesn't compile in obvious cases

此静态方法编译:

public static void Foo<TValue>(Func<TValue> factory = null)
{
    factory?.Invoke();
}

为什么不呢?然而,这个不是:

public static void Foo<TValue>(Func<TValue> factory = null)
{
    var x = factory?.Invoke();
}

使用 return 值似乎有所不同:

当然,运算符 ?. 不应用于 TValue 类型的操作数,而是应用于 Func<TValue> 类型的操作数,这就是为什么它在不使用表达式值。

非通用案例工作得很好:

public static void Bar(Func<String> factory = null)
{
    var x = factory?.Invoke();
}

尝试添加 where TValue: class 以确保 TValue 可以是 null:

static void Foo<TValue>(Func<TValue> factory = null) where TValue: class

在这种情况下,编译器可以将 x 的类型推断为 TValue 并在需要时将 null 分配给它(例如在 factory == null 的情况下)。

或尝试

static void Foo<TValue>(Func<TValue> factory = null) where TValue: struct

在那种情况下,推导的类型将是 TValue?。 (致谢 @hvd。)

想想 factory?.Invoke(); 应该解析成什么类型​​。 (如果您不在此处使用 var,则需要进行练习。)它应该是什么类型?

要判断它是什么类型需要通过这个值的计算方式来思考。如果委托不为空,则需要调用它并将操作解析为 TValue,即委托 returns。但是,如果委托是 null,则表达式 factory?.Invoke(); 需要解析为 null,因此 TValue 需要是可空类型。那么如果 TValue 不可为空怎么办,如果不是,那么该表达式不能是 TValue 类型,但是 应该 是什么?