简体   繁体   English

接线员'?' 不能应用于'T'类型的操作数(2)

[英]Operator '?' cannot be applied to operand of type 'T' (2)

I came across a weird behavior of C# compiler (VS 2015). 我遇到了C#编译器的奇怪行为(VS 2015)。 In the code bellow, compiler is happy with Value2, but complains about Value1: Operator '?' 在下面的代码中,编译器对Value2感到满意,但抱怨Value1:Operator'?' cannot be applied to operand of type 'T' 不能应用于'T'类型的操作数

Why? 为什么?

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;
}

I believe the problem is that the compiler can't know the type of the expression _valueProvider?.Value . 我认为问题是编译器无法知道表达式_valueProvider?.Value的类型_valueProvider?.Value

Let's simplify this a bit: 让我们简化一下:

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

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

What should the compiler infer the type of mystery to be? 编译器应该推断出mystery的类型是什么?

  • If T is a reference type or a nullable value type, it would make sense for the expression (and therefore mystery ) to be of type T . 如果T是引用类型或可空值类型,则表达式(因此也是mystery )属于T类型是有意义的。

  • If T is a non-nullable value type, it would make sense for the expression (and therefore mystery ) to be of type T? 如果T是一个不可为空的值类型,那么表达式(因而也是mystery )是T?型的意义T? .

As there are no constraints on T , there's no suitable type to be used, so there's a (slightly unfortunate) error message. 由于没有对T约束,因此没有合适的类型可供使用,因此存在(稍微不幸)错误消息。

If the property were of type string , int or int? 如果属性是stringintint?类型int? , all of those would be fine, and the expression would be of type string , int? ,所有这些都没问题,表达式的类型为stringint? and int? int? respectively. 分别。 But there's no equivalent of that for T . 但是对于T没有相同的东西。

If you constrain T to be a reference type, it's fine, and the expression is of type T : 如果你将T约束为引用类型,那很好,表达式是T类型:

public static void Foo<T>(IValueProvider<T> provider) where T : class
{
    // Variable is of type T
    var mystery = provider?.Value;
}

If you constrain T to be a non-nullable value type it's fine, and the expression is of type T? 如果你将T限制为一个不可为空的值类型,它就没问题,而且表达式是T?类型的T? (aka Nullable<T> ). (又名Nullable<T> )。

public static void Foo<T>(IValueProvider<T> provider) where T : struct
{
    // Variable is of type Nullable<T>
    var mystery = provider?.Value;
}

But without either constraint, there's no valid translation. 但是没有任何限制,就没有有效的翻译。

This code: 这段代码:

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

public class Validator<T>
{
    public Validator(IValueProvider<T> provider)
    {
        var providerValue = provider?.Value;
    }
}

Shows this error at provider?.Value : provider?.Value显示此错误provider?.Value

Operator '?' 接线员'?' cannot be applied to operand of type 'T' 不能应用于'T'类型的操作数

And ReSharper gives this hint: ReSharper给出了这个提示:

Can't lift conditional access expression type T to nullable type 无法将条件访问表达式类型T提升为可空类型

Because the type of provider.Value is T , which isn't constrained, so you could pass a non-nullable type for T . 因为provider.Value的类型是T ,它不受约束,所以你可以为T传递一个不可为空的类型。

Say you'd use it with var validator = new Validator<int>(null); 假设你使用var validator = new Validator<int>(null); , then this'd happen: 那么这会发生:

var providerValue = provider?.Value;

ie

int providerValue = null;

Which isn't allowed, as int isn't nullable. 这是不允许的,因为int不可为空。

The rest of the errors trickles down from there. 其余的错误从那里涓涓细流。 So constrain T to be a nullable type, so for example where T : class , and it'll work. 因此将T限制为可以为空的类型,例如where T : class ,它就可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM