繁体   English   中英

创建不可变类的新实例时节省价值

[英]Save value when create new instance of immutable class

我有一个不变的班级F1:

public class F1
{
    public readonly int field1;
    public readonly int field2;
    public readonly int field3;
    public readonly int field4;
    public readonly int field5;

    ......

    public F1 SetField1(int f)
    {
        return new F1(f, field2, field3, field4, field5);
    }
    ......

}

如果我需要更改一个字段,例如field1,则需要从该方法返回类的新实例。 所有五个字段都传递给构造函数,即使其中四个没有更改也是如此。

可以,如果我使用5个字段。 但是,如果我使用40个字段,并且无法将40个参数传递给构造函数。 我需要做什么? 如何在不将参数传递给构造函数的情况下保存其他字段的值并创建新实例?

我真的需要一成不变的课程。 这是我工作的重要条件。

使用每个类从Object继承的Object.MemberwiseClone()方法。

public class F1
{
    private int _field1;
    public int Field1 { get return _field1; }

    private int _field2;
    public int Field2 { get return _field2; }

    private int _field3;
    public int Field3 { get return _field3; }

    ...

    public F1 SetField1(int f)
    {
        var f1 = (F1)MemberwiseClone();
        f1._field1 = f;
        return f1;
    }

    ...
}

通过使用只读属性(仅具有getter而没有setter的属性)公开字段,可以实现不变性。

请注意, MemberwiseClone仅对原始对象进行浅表复制。 如果该对象仅包含值类型的字段,或者所有引用类型的字段也都是不可变的(例如,例如string ,则可以。 否则,您可能也必须克隆这些字段。

具有40个字段的类似乎非常复杂,请尝试将其重构为几个较小的类。

为了避免编写太多样板代码,您可以使用可选的可为空的参数(Carsten建议,他的评论中类似)

class ImmutableClass
{
    private readonly int _field1;
    private readonly int _field2;

    public ImmutableClass(int field1, int field2)
    {
        _field1 = field1;
        _field2 = field2;
    }

    private ImmutableClass(ImmutableClass src, int? field1 = null, int? field2 = null)
    {
        _field1 = field1 ?? src._field1;
        _field2 = field2 ?? src._field2;
    }

    //choose a more domain-related name
    public ImmutableClass ModifyField1(int value)
    {
        return new ImmutableClass(this, field1: value);
    }

    //choose a more domain-related name
    public ImmutableClass ModifyField2(int value)
    {
        return new ImmutableClass(this, field2: value);
    }

    //just an example - I wouldn't do it in my code
    public ImmutableClass ModifyFields(int? field1 = null, int? field2 = null)
    {
        return new ImmutableClass(this, field1, field2);
    }
}

您还可以将可变字段与私有设置器一起使用。 这将允许您使用诸如自动映射器之类的工具来创建副本并设置修改后的字段,然后再返回新实例。 但是,可以使用反射来更改此类。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM