有人可以告诉我为什么注释的代码行(最后一个)不能编译吗?它跟它后面的行不一样吗?

public struct OtherStruct
{
    public int PublicProperty { get; set; }
    public int PublicField;

    public OtherStruct(int propertyValue, int fieldValue)
        : this()
    {
        PublicProperty = propertyValue;
        PublicField = fieldValue;
    }

    public int GetProperty()
    {
        return PublicProperty;
    }
    public void SetProperty(int value)
    {
        PublicProperty = value;
    }
}

public struct SomeStruct
{
    public OtherStruct OtherStruct { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        SomeStruct a = new SomeStruct();
        //a.OtherStruct.PublicProperty++;
        a.OtherStruct.SetProperty(a.OtherStruct.GetProperty() + 1);
    }
}

最佳答案

SomeStruct.OtherStruct是一个属性,返回一个值-它不是变量。这行:

a.OtherStruct.PublicProperty++;

就像打电话:
a.get_OtherStruct().PublicProperty++;

因为表达式a.get_OtherStruct()是一个值而不是一个变量,所以有点像这样做:
OtherStruct tmp = a.get_OtherStruct();
tmp.PublicProperty++;

更改属性返回的PublicProperty副本中OtherStruct的值根本不会更改原始值。几乎可以肯定,这不是您的意图。 C#设计人员预见到了这种问题,并设法在许多情况下将其禁止。

请注意,如果OtherStruct而是引用类型(一个类),则将是复制的引用,而不是其中的值...,因此更改tmp.PublicProperty会有所不同。有关更多信息,请参见我的article on reference and value types

顺便说一句,像这样的可变结构通常不是一个好主意。它们会引起各种问题,并导致难以预测的代码。

编辑:响应您的“答案”,两行不同:a.OtherStruct属性表达式不是赋值运算符或复合赋值运算符的目标。

您可以争辩说,您希望以允许这种方式的方式定义C#(尽管我仍然不同意),但是编译器正确地实现了规范。有关更多详细信息,请参见C#3.0规范的10.7.2节。

10-08 04:31