[英]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?
如果属性是string
, int
或int?
类型int?
, all of those would be fine, and the expression would be of type string
, int?
,所有这些都没问题,表达式的类型为string
, int?
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.