C# 空条件运算符不使用可空类型?
我正在用c#6编写一段代码,出于某种奇怪的原因,这是可行的C# 空条件运算符不使用可空类型?,c#,null-coalescing-operator,c#-6.0,C#,Null Coalescing Operator,C# 6.0,我正在用c#6编写一段代码,出于某种奇怪的原因,这是可行的 var value = objectThatMayBeNull?.property; 但这并不是: int value = nullableInt?.Value; “不工作”是指我得到一个编译错误,说无法解析符号“Value”。 知道为什么空条件运算符?。不起作用吗?int没有值属性 考虑: var value = obj?.Property 相当于: value = obj == null ? null : obj.Proper
var value = objectThatMayBeNull?.property;
但这并不是:
int value = nullableInt?.Value;
“不工作”是指我得到一个编译错误,说无法解析符号“Value”
。
知道为什么空条件运算符
?。
不起作用吗?int
没有值
属性
考虑:
var value = obj?.Property
相当于:
value = obj == null ? null : obj.Property;
这对于int
来说毫无意义,因此通过使用int?
就没有意义了。
旧的GetValueOrDefault()
对于int?
是有意义的
或者,由于?
必须返回可为空的内容,因此只需:
int? value = nullableInt;
好的,我做了一些思考和测试。情况就是这样:
int value = nullableInt?.Value;
编译时给出此错误消息:
类型“int”不包含“Value”的定义
这意味着?
将int?
转换为实际的int
值。这实际上与:
int value = nullableInt ?? default(int);
结果是一个整数,显然没有值
好的,这有帮助吗
int value = nullableInt?;
不,不允许使用这种语法
那又怎样?对于这种情况,只需继续使用.GetValueOrDefault()
int value = nullableInt.GetValueOrDefault();
关于可为null的类型,?。
运算符表示如果不为null,请使用包装值
。因此,对于可为null的int,如果可为null的值为8
,则?
的结果将是8
,而不是包含8
的可为null的值。由于Value
不是int
的属性,因此会出现错误
因此,尝试使用propertyValue
的示例完全失败了,但下面的方法可行
var x=nullableInt?.ToString()代码>
考虑空合并运算符,??
var x=nullableInt??0;代码>
这里,操作符说,如果为null,则返回0,否则返回可为null的
中的值,在本例中,该值是一个int
。?。
运算符在提取可空值的内容方面执行类似的操作
对于您的特定示例,您应该使用?
运算符和适当的默认值,而不是。
运算符。原因是使用空条件运算符访问值将毫无意义:
- 当应用
x?.p
时,其中p
是不可为空的值类型T
,结果为类型T?
。出于同样的原因,nullableInt?.Value
操作的结果必须可以为null
- 当您的
nullableInt
具有值时,nullableInt?.value
的结果将与值本身相同
- 当您的
null
没有值时,结果将是null
,这与值本身相同
尽管使用?。
运算符访问值
没有意义,但访问可空值类型的其他属性也有意义。运算符与可空值类型和引用类型一致,因此这两种实现产生相同的行为:
class PointClass {
public int X { get; }
public int Y { get; }
public PointClass(int x, int y) { X = x; Y = y; }
}
struct PointStruct {
public int X { get; }
public int Y { get; }
public PointStruct(int x, int y) { X = x; Y = y; }
}
...
PointClass pc = ...
PointStruct? ps = ...
int? x = pc?.X;
int? y = ps?.Y;
在可为空的结构
的情况下,运算符允许您访问基础类型PointStruct
的属性,并以与引用类型PointClass的不可为空属性相同的方式将可为空性添加到结果中。我基本上同意其他答案。我只是希望观察到的行为能够得到某种形式的权威文件的支持
由于我在任何地方都找不到C#6.0规范(是否已经发布了?),因此我发现最接近“文档”的是。假设在那里发现的信息仍然反映了当前的情况,下面是正式解释观察到的行为的相关部分
语义类似于将三元运算符应用于空等式检查、空文本和运算符的无问号应用程序,只是表达式只计算一次:
e?.m(…) => ((e == null) ? null : e0.m(…))
e?.x => ((e == null) ? null : e0.x)
e?.$x => ((e == null) ? null : e0.$x)
e?[…] => ((e == null) ? null : e0[…])
其中e0
与e
相同,除非e
是可空值类型,在这种情况下e0
是e.value
将最后一条规则适用于:
nullableInt?.Value
。。。语义等价的表达式变为:
((nullableInt == null) ? null : nullableInt.Value.Value)
显然,nullableInt.Value.Value
无法编译,这就是您观察到的
至于为什么设计决定将特殊规则应用于可空类型,我认为dasblinkenlight
的回答很好地涵盖了这一点,所以我不在这里重复
此外,我应该提到,即使假设我们没有针对可空类型的特殊规则,并且表达式nullableInt?.Value
的编译和行为与您最初认为的一样
// let's pretend that it actually gets converted to this...
((nullableInt == null) ? null : nullableInt.Value)
但是,您的问题中的以下陈述将无效并产生编译错误:
int value = nullableInt?.Value; // still would not compile
它仍然不起作用的原因是nullableInt?.Value
表达式的类型是int?
,而不是int
。因此,您需要将值
变量的类型更改为int?
这也正式包含在以下内容中:
结果的类型取决于基础运算符右侧的类型T
:
- 如果
T
是(已知的)引用类型,则表达式的类型是T
- 如果
T
是(已知的)不可为空的值类型,则表达式的类型是T?
- 如果
T
是(已知的)可空值类型,则表达式的类型为T
- 否则
int? value = nullableInt?.Value;
int? value = nullableInt;
var value = objectThatMayBeNull?.property;
var value = (objectThatMayBeNull == null) ? null : objectThatMayBeNull.property
int value = nullableInt?.Value;
int value = (nullableInt == null) ? null : nullableInt.Value.Value;