?。 C# 中的运算符由于未知原因未编译
?. operator in C# not compiling for unknown reason
在以下代码中,两个变体之一无法编译:
class C
{
public decimal DecimalField;
}
static C GetC() { return new C(); } //Can return null in reality.
C c = GetC(); //Get a C value from somewhere, this might be null
string toString1 = c?.DecimalField?.ToString(); //Does not compile.
string toString2 = (c?.DecimalField)?.ToString(); //Compiles.
Error CS0023: Operator '?' cannot be applied to operand of type 'decimal'
为什么简单形式无法编译?
表达式 c?.DecimalField
不是 decimal?
类型吗?该值可以为 null,因此应该应用 ?.
运算符。我很确定是这样,因为在这段代码中:
var decimalValue = c?.DecimalField;
var
根据 IDE 解析为 decimal?
。
decimal类型不能为null,所以null-coalesce运算符在这里没有意义。只需将 toString1 设置为某个值即可。
如果您想在所有情况下编译它,您应该通过在您的 decimal
中添加 decimal ?
insted 来编辑您要与可空类型进行比较的 DecimalField
字段定义。
类型 decimal
不是可为空的类型。因此,您的第一个表达式无法编译。与第二个语句的不同之处在于,如果 c
是 null
,则括号的内部部分可能已经是 null
。因此它编译。
这可能导致 null
值:(c?.DecimalField)
结果类型为System.Nullable<decimal>
或简写decimal?
您有三个变体。
您可以设置默认值,它 returns DecimalField
或 "0"
:
string toString = c?.DecimalField.ToString() ?? decimal.Zero.ToString();
没有默认值,它returns DecimalField
或 null
:
string toString = c?.DecimalField.ToString();
或者您可以使 DecimalField
可为空,它 returns DecimalField
或 null
:
public decimal? DecimalField;
...
string toString1 = c?.DecimalField?.ToString(); //Compile now!
这是因为空条件访问运算符是 "short-circuiting"。也就是说,如果你写成a?.b.c
然后执行,a
是null
,那么不仅.b
不执行,而且.c
也不执行。
因此,当您编写 a?.b?.c
时,第二个空条件访问运算符不是关于检查 a
或 a.b
是否为 null
。 仅检查a.b
是否为null
。因此,如果 a.b
永远不可能是 null
,就像您的情况一样,使用 null 条件访问运算符是没有意义的,这就是语言不允许它的原因。
这也解释了为什么 a?.b?.c
和 (a?.b)?.c
不是一回事。
有关此的更多信息,您可以阅读 the C# Language Design Meeting notes where this was decided。
在以下代码中,两个变体之一无法编译:
class C
{
public decimal DecimalField;
}
static C GetC() { return new C(); } //Can return null in reality.
C c = GetC(); //Get a C value from somewhere, this might be null
string toString1 = c?.DecimalField?.ToString(); //Does not compile.
string toString2 = (c?.DecimalField)?.ToString(); //Compiles.
Error CS0023: Operator '?' cannot be applied to operand of type 'decimal'
为什么简单形式无法编译?
表达式 c?.DecimalField
不是 decimal?
类型吗?该值可以为 null,因此应该应用 ?.
运算符。我很确定是这样,因为在这段代码中:
var decimalValue = c?.DecimalField;
var
根据 IDE 解析为 decimal?
。
decimal类型不能为null,所以null-coalesce运算符在这里没有意义。只需将 toString1 设置为某个值即可。
如果您想在所有情况下编译它,您应该通过在您的 decimal
中添加 decimal ?
insted 来编辑您要与可空类型进行比较的 DecimalField
字段定义。
类型 decimal
不是可为空的类型。因此,您的第一个表达式无法编译。与第二个语句的不同之处在于,如果 c
是 null
,则括号的内部部分可能已经是 null
。因此它编译。
这可能导致 null
值:(c?.DecimalField)
结果类型为System.Nullable<decimal>
或简写decimal?
您有三个变体。
您可以设置默认值,它 returns DecimalField
或 "0"
:
string toString = c?.DecimalField.ToString() ?? decimal.Zero.ToString();
没有默认值,它returns DecimalField
或 null
:
string toString = c?.DecimalField.ToString();
或者您可以使 DecimalField
可为空,它 returns DecimalField
或 null
:
public decimal? DecimalField;
...
string toString1 = c?.DecimalField?.ToString(); //Compile now!
这是因为空条件访问运算符是 "short-circuiting"。也就是说,如果你写成a?.b.c
然后执行,a
是null
,那么不仅.b
不执行,而且.c
也不执行。
因此,当您编写 a?.b?.c
时,第二个空条件访问运算符不是关于检查 a
或 a.b
是否为 null
。 仅检查a.b
是否为null
。因此,如果 a.b
永远不可能是 null
,就像您的情况一样,使用 null 条件访问运算符是没有意义的,这就是语言不允许它的原因。
这也解释了为什么 a?.b?.c
和 (a?.b)?.c
不是一回事。
有关此的更多信息,您可以阅读 the C# Language Design Meeting notes where this was decided。