C# 为什么我可以对不可变的'struct'执行此操作?

C# 为什么我可以对不可变的'struct'执行此操作?,c#,struct,xml-serialization,immutability,C#,Struct,Xml Serialization,Immutability,最近我不得不序列化一个包含复杂(不可变)结构的类。我一直失败,直到我想出了这个办法(请参见ReadXml()) 考虑以下代码: [ImmutableObject(true)] public struct Point : IXmlSerializable { readonly int x, y; public Point(int x, int y) { this.x=x; this.y=y; } public Poi

最近我不得不序列化一个包含复杂(不可变)结构的类。我一直失败,直到我想出了这个办法(请参见
ReadXml()

考虑以下代码:

[ImmutableObject(true)]    
public struct Point : IXmlSerializable
{
    readonly int x, y;

    public Point(int x, int y)
    {
        this.x=x;
        this.y=y;
    }
    public Point(Point other)
    {
        this=other;
    }
    public int X { get { return x; } }
    public int Y { get { return y; } }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }
    public void ReadXml(System.Xml.XmlReader reader)
    {
        // Immutable, right?
        int new_x =0, new_y=0;
        int.TryParse(reader.GetAttribute("X"), out new_x);
        int.TryParse(reader.GetAttribute("Y"), out new_y);
        // But I can change the contents by assigning to 'this'
        this=new Point(new_x, new_y);
    }
    public void WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteAttributeString("X", X.ToString());
        writer.WriteAttributeString("Y", Y.ToString());
    }
}

public class Foo
{
    Point from, to;
    public Foo() { }
    public Foo(Point from, Point to)
    {
        this.from=from;
        this.to=to;
    }
    public Point From { get { return from; } set { from=value; } }
    public Point To { get { return to; } set { to=value; } }
}
正确读入以下xml文件


我的问题是这=新的点(新的x,新的y)在内容不可变时工作(
只读
)关键字?是什么阻止我添加这样的成员

    public void Reset()
    {
        this=new Point(0, 0);
    }
    public void Add(Point other)
    {
        this=new Point(x+other.x, y+other.y);
    }
哪些改变了我的结构的内容

    {
        Point foo=new Point(10, 15);
        // foo.X=10, foo.Y=15
        Point bar=new Point(foo);   // Clone
        // bar.X=10, bar.Y=15

        foo.Reset();
        // foo.X=0, foo.Y=0

        bar.Add(bar);
        // bar.X=20, bar.Y=30
    }

我很高兴这个功能的存在,因为它允许我用Xml文件读/写不可变的结构,它的工作非常令人惊讶。

没有任何东西可以阻止您编写
重置
。事实上,它不会有任何问题

可以使用readonly关键字,因为您实际上是在创建一个新结构,而不是修改原始结构

以下是代码和生成的IL:

public void Reset()
{
    this = new Point(0,0);
}

IL_0000:  nop         
IL_0001:  ldarg.0     
IL_0002:  ldc.i4.0    
IL_0003:  ldc.i4.0    
IL_0004:  newobj      UserQuery+Point..ctor
IL_0009:  stobj       UserQuery.Point
IL_000E:  ret
注意
newobj
调用


正如所说:

结构和类在默认情况下不是不可变的,尽管使结构不可变是最佳做法。因此,属性中有
只读
关键字、私有字段和仅getter。所有,除了覆盖字段的
ReadXml
。这让很多人感到惊讶。请参阅@EricLippert伟大的文章。尽管字段偏移量和
out
参数可能会引发标志。直接分配给
这个
实际上对程序员有很大的好处。我很高兴它在那里,但也有点惊讶。所以结构是原子的,不可变的。如果它有
readonly
关键字,你可以不更改任何内容,也可以全部更改。我的博客文章中指向实际解释情况的文章的链接已断开。文章可在此处找到: