C# 为什么编译器不能解决这个问题?(物业)

C# 为什么编译器不能解决这个问题?(物业),c#,compiler-construction,properties,C#,Compiler Construction,Properties,在处理易变结构和属性时,我觉得奇怪的是,编译器可以解决一些问题,但不能解决其他显而易见的问题 以以下自动属性为例: Vector2 Vector { get; set; } 而不是键入以下内容: Vector2 v = Vector; v += new Vector2(5, 7); Vector = v; 编译器足够聪明,可以让我这么做:结构的易变性在这里没有任何影响 Vector += new Vector2(5, 7); 但编译器似乎不够聪明,无法让我执行以下操作,即使我可以访问set

在处理易变结构和属性时,我觉得奇怪的是,编译器可以解决一些问题,但不能解决其他显而易见的问题

以以下自动属性为例:

Vector2 Vector { get; set; }
而不是键入以下内容:

Vector2 v = Vector;
v += new Vector2(5, 7);
Vector = v;

编译器足够聪明,可以让我这么做:结构的易变性在这里没有任何影响

Vector += new Vector2(5, 7);
但编译器似乎不够聪明,无法让我执行以下操作,即使我可以访问setter和getter-

Vector.X += 4;
相反,我被迫“手动”执行此操作-

Vector2 v = Vector;
v.X += 4;
Vector = v;
编译器团队决定允许第一种速记形式而不允许第二种形式,有什么特别的原因吗? 除了建议的方法明显更简洁之外,我还认为它可能允许更有效的NGEN/JIT内联,因为很明显,getter生成的副本不会在其他任何地方使用。如果Vector2是一个结构a值类型,那么赋值给someObject.Vector.X将赋值给Vector属性返回的临时副本。这是没有道理的,因此是不允许的

有关常规参考和一些链接,请参阅。

如果Vector2是一个结构a值类型,则分配给someObject.Vector.X将分配给Vector属性返回的临时副本。这是没有道理的,因此是不允许的


有关一般参考和一些链接,请参见。

这不是编译器是否足够聪明的问题,而是代码编译成什么的问题

Vector += new Vector2(5, 7);
编译成

Vector = Vector + new vector2(5,7);
var v = Vector;
v.X = v.X + 2
所以我们有一个任务。都很好

Vector.X += 2;
编译成

Vector = Vector + new vector2(5,7);
var v = Vector;
v.X = v.X + 2

没有返回向量的赋值

这不是编译器是否足够聪明的问题,而是代码编译成什么的问题

Vector += new Vector2(5, 7);
编译成

Vector = Vector + new vector2(5,7);
var v = Vector;
v.X = v.X + 2
所以我们有一个任务。都很好

Vector.X += 2;
编译成

Vector = Vector + new vector2(5,7);
var v = Vector;
v.X = v.X + 2


没有返回向量的赋值

虽然我不能直接回答你的问题——为什么不直接用零的y分量进行加法或减法呢?@VaughanHilts这是可能的,但是如果不是矢量2而是矢量4呢?这对我来说似乎不是很“干净”:向量+=新向量44,0,0,0;假设向量X+=4;因为向量为空,所以不起作用。Vector为空是因为编译器没有假设您要在属性中指向哪个Vector对象。@RobertHarvey Vector2是一个结构,所以它不能为空。虽然我不能直接回答您的问题-为什么不直接用零的y分量进行加法或减法?@VaughanHilts这是可能的,但是如果不是矢量2而是矢量4呢?这对我来说似乎不是很“干净”:向量+=新向量44,0,0,0;假设向量X+=4;因为向量为空,所以不起作用。Vector为null,因为编译器没有假设您要在属性中指向哪个Vector对象。@RobertHarvey Vector2是一个结构,所以不能为null。Vector.X+=2实际上目前根本不进行编译。@Read as translates to。编译器非常聪明,知道这永远不会产生任何效果,所以有一个特定的错误或警告?因为如果程序员这样做,几乎肯定会犯错误。编译器只知道这是不允许的。同样,编译器团队也可以选择不允许将+=与属性一起使用,因为这看起来也像是对副本进行了变异,不是通过setter实际发送值。Vector.X+=2实际上目前根本不编译。编译器足够聪明,知道这永远不会产生任何效果,因此存在特定的错误或警告?因为如果程序员这样做,几乎肯定会犯错误。编译器只知道这是不允许的。同样,编译器团队也可以选择不允许将+=与属性一起使用,因为这看起来也像是对副本进行了变异,而不是通过setter实际发送值。Vector+=new Vector24,0似乎也只是对副本进行了变异,但编译器团队决定将其作为其他东西实现。我的问题是——为什么他们没有选择对我的另一个例子做同样的事情呢?@不,另一个样本不是变异副本,而是变异实际值,这就是为什么它被允许。它实际上是有意义的,因为它没有变异,它完全替换了整个向量变量,用一个新实例完全覆盖了它的内容。这与只指定结构的一个属性非常不同。请参阅上面的链接。@Servy@GSerg我指的不是编译器的实际功能,而是它的外观。因为Vector.X+=4根本不编译,所以这个答案只能反映这段代码的外观,现在是它实际编译的方式。既然没有t@Acidic它看起来像是在改变一个属性
对某些对象的描述是错误的,但事实上它并没有发生。这就是为什么编译器发现这是一个错误。它可以让你做得很好,并且编译得很好,但是你会一直想知道为什么你的Vector.X实际上没有改变。参见和.Vector+=newvector24,0似乎也只是简单地改变了一个副本,但编译器团队决定将其作为其他东西实现。我的问题是——为什么他们没有选择对我的另一个例子做同样的事情呢?@不,另一个样本不是变异副本,而是变异实际值,这就是为什么它被允许。它实际上是有意义的,因为它没有变异,它完全替换了整个向量变量,用一个新实例完全覆盖了它的内容。这与只指定结构的一个属性非常不同。请参阅上面的链接。@Servy@GSerg我指的不是编译器的实际功能,而是它的外观。因为Vector.X+=4根本不编译,所以这个答案只能反映这段代码的外观,现在是它实际编译的方式。既然没有t@Acidic这看起来像是更改了某个对象的某个属性,但实际上并没有发生。这就是为什么编译器发现这是一个错误。它可以让你做得很好,并且编译得很好,但是你会一直想知道为什么你的Vector.X实际上没有改变。请参阅和。