c# - 更改不可变类型的属性

标签 c# clone immutability icloneable

我在一个临时的 CQRS 读取存储中存储了不可变类型(查询/读取端,实际上是由一个带有抽象访问层的简单列表实现的,此时我不想使用一个完整的文档数据库)。这些阅读商店包含如下项目:

public class SomeItem
{
    private readonly string name;
    private readonly string description;

    public SomeItem(string name, string description)
    {
        this.name = name;
        this.description = description;
    }

    public string Name
    {
        get { return this.name; }
    }

    public string Description
    {
        get { return this.description; }
    }
}

现在我想更改名称并在第二个命令中更改描述。 这些更改应保持当前状态,这意味着对于上面的示例:

// initial state
var someItem = new SomeItem("name", "description");

// update name -> newName
someItem = new SomeItem("newName", someItem.Description);

// update description -> newDescription
someItem = new SomeItem(someItem.Name, "newDescription");

如果您有多个属性,这对我来说确实容易出错……您必须设法保持当前状态。我可以为每种类型添加类似 Clone() 的东西,但我认为/希望有更好的东西,性能好且易于使用,我不想写太多重复的代码(懒惰的程序员)。有什么建议可以改进上面的代码吗? SomeItem 类需要保持不变(通过多个不同的线程传输)。

最佳答案

遗憾的是,C# 中没有简单的方法。 F# 有 with 关键字,你可以看看 lenses,但在 C# 中这一切都有些乏味。我能给你的最好的是这样的:

class SomeItem
{
  private readonly string name;
  private readonly string description;

  public SomeItem(string name, string description)
  {
    this.name = name;
    this.description = description;
  }

  public SomeItem With
    (
      Option<string> name = null,
      Option<string> description = null
    )
  {
    return new SomeItem
      (
        name.GetValueOrDefault(this.name), 
        description.GetValueOrDefault(this.description)
      );
  }
}

这使您可以像这样进行更新

var newItem = oldItem.With(name: "My name!");

我已经将这种方法与扩展方法和 T4 一起使用,效果很好,但即使您手动编写代码,它也相当可靠——如果您添加一个新字段,则必须将它添加到 With 也是如此,所以它工作得很好。

如果您愿意容忍运行时代码生成和降低类型安全性,还有其他几种方法,但这有点违背 IMO 的原则。

关于c# - 更改不可变类型的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38789031/

相关文章:

c# - MVC 全局错误处理 : Application_Error not firing

c# - 如何在 C# 中克隆图形?

c# - 如何克隆微软图表控件?

javascript - 如何使 jQuery 函数在克隆的元素上执行?

c# - "Immutable strings are threadsafe"是什么意思

c# - C#编译如何避免需要头文件?

c# - 使用 OpenXML 创建合并单元格

scala - 用不可变对象(immutable对象)模拟继承+可变状态

java - 在 Brian Goetz 的 Java Concurrency in Practice 中,为什么点类是不可变的,它被 DelegatingVehicleTracker 使用

c# - 为什么 HTML 助手 EditorFor of type file 在 C# 和 ASP.NET MVC 中生成多个文件字段?