空值条件运算符不能用于赋值?

4
请查看以下代码,并帮我理解为什么会出现编译器错误。
class Program
{
    static void Main(string[] args)
    {
        Sample smpl = GetSampleObjectFromSomeClass();

        //Compiler Error -- the left-hand side of an assignment must be a variable property or indexer
        smpl?.isExtended = true; 
    }
}

public class Sample
{
    public bool isExtended { get; set; }
}

我应该理解为 null 条件语句只用于访问属性、变量等,而不用于赋值吗?
注:我参考了一个类似的帖子(下面链接),但我认为讨论不够充分。 为什么 C# 6.0 在使用 Null 传播运算符时不允许设置非空可空结构的属性? 编辑: 我期望得到的是这样的:

If(null!= smpl) 
{ 
smpl.isExtended = true; 
}

看起来我的期望不太正确!


4
您的推断是正确的。空值条件运算符只适用于成员访问,而不适用于赋值操作。我倾向于同意编译器应该允许将其用于属性赋值(但不包括字段),因为属性赋值实际上被编译为方法调用。已编译的属性赋值看起来像这样:smpl?.set_isExtended(true); 这将是完全有效的代码。 - Andrew Hanlon
1
@AndrewHanlon:有趣的观察(+1),但语义和语法很难完全协同工作。 - leppie
2
不确定为什么人们会问“你希望它做什么” - 对于程序员来说,你期望它做什么是显而易见的:如果它不为空,则进行赋值。 - Lee Gunn
2
我的猜测是在C#语言中,空条件运算符不是有效的左值。@jonskeet,请回答。 - leppie
1
@Servy:抱歉,我没有意识到SO已经变成了类似于Experts Exchange的地方,只有问题和答案是适用的。显然,评论功能是无用的,可能应该被删除。 - leppie
显示剩余22条评论
2个回答

6
您的推断是正确的。空值条件运算符仅适用于成员访问,而不适用于赋值。
话虽如此,我倾向于同意语言/编译器应该允许使用该运算符进行属性赋值(但不是字段),因为属性赋值实际上编译为方法调用。
编译后的属性赋值将看起来像:
smpl?.set_isExtended(true); 

这将是完全有效的代码。

另一方面,可以说它会引入属性和字段使用之间目前不存在的语法差异,并使代码更难以理解。

您还可以在codeplex上访问大多数C# 6.0设计注释。我进行了粗略的扫描,空值条件讨论涵盖了许多部分。


3
考虑一下这行代码的含义:
smpl?.isExtended = true;

如果smplnull,那么你会尝试将一个值赋给null,这没有任何意义。只需直接赋值即可,不需要检查null
smpl.isExtended = true;

基本上,空值传播操作符应该用于读取值,而不是用于设置值。考虑下面这行代码:
var x = someObject?.someProperty;

从概念上讲,这意味着如果someObject存在,则将为x分配someProperty的值。如果它不存在(为null),那么x将是null

相反地,这意味着什么?:

someObject?.someProperty = x;

从概念上讲,这意味着如果someObject存在,则将someProperty设置为x。但是,如果它不存在(即为null),那么将null设置为x?这没有意义:

null = x;

只是为了让我的观点更清晰,我进行了编辑,@David - Vivek Shukla
@Vivek_Shukla:我也更新了答案。基本上,考虑在任一情况下代码会发生什么(是“null”还是不是“null”)。其中两种情况中的一种毫无意义。因此编译器拒绝它。 - David
2
它的意思不是:如果 someObject 存在,则调用 someObject.set_someProperty(x),否则什么也不做。 - Lee Gunn
1
我也是这么想的,@LeeGunn - Vivek Shukla
1
正如@LeeGunn所暗示的那样,这个属性在这种情况下只是一个设置方法吗?我不明白。看起来像是一个疏忽。 - Brian Ortiz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接