4

在以下代码中,两个变体之一无法编译:

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.

错误 CS0023:操作员“?” 不能应用于“十进制”类型的操作数

为什么简单表单无法编译?

表达式c?.DecimalField不会是 typedecimal?吗?该值可以为 null,因此?.应应用运算符。我很确定这是因为在这段代码中:

var decimalValue = c?.DecimalField;

var确实根据decimal?IDE解析。

4

4 回答 4

3

这是因为空条件访问运算符是“短路的”。也就是说,如果你用being编写a?.b.c并执行它,那么不仅不执行,而且也不执行。anull.b.c

因此,当您编写 时a?.b?.c,第二个空条件访问运算符不是检查a是否a.bnull。这只是关于检查是否a.bnull. 所以, if a.bcan never be null,就像你的情况一样,使用空条件访问运算符是没有意义的,这就是语言不允许它的原因。

这也解释了为什么a?.b?.c(a?.b)?.c不是一回事。

有关这方面的更多信息,您可以阅读决定这一点的 C# 语言设计会议记录

于 2017-07-15T16:40:23.670 回答
2

该类型decimal不是可为空的类型。因此,您的第一个表达式无法编译。与第二个语句的不同之处在于括号的内部部分可能已经是nullif cwas null。因此它编译。

这可能会产生一个null值:(c?.DecimalField)

结果类型是System.Nullable<decimal>或短写decimal?

于 2017-07-11T12:10:22.580 回答
0

你有三个变种。

您可以设置默认值,它返回DecimalField"0"

string toString = c?.DecimalField.ToString() ?? decimal.Zero.ToString();

没有默认值,它返回DecimalFieldor null

string toString = c?.DecimalField.ToString();

或者你可以使DecimalField空,它返回DecimalFieldnull

public decimal? DecimalField;
...
string toString1 = c?.DecimalField?.ToString(); //Compile now!
于 2017-07-11T12:17:22.070 回答
0

十进制类型不能为空,因此空合并运算符在这里没有意义。只需将 toString1 设置为某个值。

如果您想在所有情况下编译它,您应该通过在字段定义中添加insted来编辑您DecimalField正在比较的可空类型。decimal ?decimal

于 2017-07-11T12:08:38.943 回答