我遇到了C#编译器的怪异行为(VS 2015)。
在下面的代码中,编译器对Value2感到满意,但提示Value1:运算符'?'不能应用于类型'T'的操作数

为什么?

public interface IValueProvider<T>
{
    T Value { get; }
}

class Validator<T>
{
    public Validator(IValueProvider<T> provider)
    {
        _valueProvider = provider;
    }

    public T Value1 => _valueProvider?.Value ?? default(T);

    public T Value2 => _valueProvider != null ? _valueProvider.Value : default(T);

    private readonly IValueProvider<T> _valueProvider;
}

最佳答案

我相信问题在于编译器无法知道_valueProvider?.Value表达式的类型。

让我们简化一下:

public interface IValueProvider<T>
{
    T Value { get; }
}

public class Test
{
    public static void Foo<T>(IValueProvider<T> provider)
    {
        var mystery = provider?.Value;
    }
}

编译器应推断mystery的类型是什么?
  • 如果T是引用类型或可为空的值类型,则表达式(因此mystery)的类型为T是有意义的。
  • 如果T是不可为空的值类型,则表达式(因此mystery)的类型为T?是有意义的。

  • 由于没有对T进行约束,因此没有合适的类型可以使用,因此会出现(稍微不幸的)错误消息。

    如果该属性的类型为stringintint?,那么所有这些都很好,并且表达式的类型分别为stringint?int?。但是T却没有等效的方法。

    如果将T约束为引用类型,那很好,表达式的类型为T:
    public static void Foo<T>(IValueProvider<T> provider) where T : class
    {
        // Variable is of type T
        var mystery = provider?.Value;
    }
    

    如果将T约束为不可为空的值类型,则可以,并且表达式的类型为T?(又名Nullable<T>)。
    public static void Foo<T>(IValueProvider<T> provider) where T : struct
    {
        // Variable is of type Nullable<T>
        var mystery = provider?.Value;
    }
    

    但是没有任何限制,就没有有效的翻译。

    关于c# - 运算符 '?'不能应用于 'T'类型的操作数(2),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44174712/

    10-12 12:45
    查看更多