修改/过滤而不改变对象

Posted

技术标签:

【中文标题】修改/过滤而不改变对象【英文标题】:Modifying/filtering without mutating object 【发布时间】:2021-09-05 02:20:08 【问题描述】:

好的,假设我有一些 C# 代码可以过滤或重组传入的对象(或对象列表),如下所示:

public Customer GetCustomer()

    var customer = _customerAdapter.GetCustomer();
    ModifyCustomer(customer);
    return customer;


private void ModifyCustomer(Customer c)

   //some changes to customer object

这可行,但我更喜欢功能更强大的方法,即保留新客户并返回新客户(修改后的客户)。

深度克隆是要走的路吗?用 C# 编码时是否推荐?

【问题讨论】:

C# 没有内置任何内容,例如,请参阅 ***.com/questions/6569486/…、***.com/questions/129389/… 等。请注意,如果涉及 ORM,这可能会出现问题。 这不就是将void ModifyCustomer(Customer c) 改为Customer ModifyCustomer(Customer c) 并相信ModifyCustomer 的内容做对了吗? 【参考方案1】:

最接近的内置功能可能是records 和with 表达式:

public record Person(string FirstName, string LastName)

    public string[] PhoneNumbers  get; init; 


Person person1 = new("Nancy", "Davolio")  PhoneNumbers = new string[1] ;
Person person2 = person1 with  FirstName = "John" ;

【讨论】:

酷!还没有(C# 9),但我一定会研究它,并在我自己的项目中使用它! @Cowborg 记录不需要任何运行时更改,因此应该可以通过在 .csproj 中设置 LangVersion 在 .net 框架中使用,即使这不受官方支持。【参考方案2】:

如果你不能使用 C# 9,那么你可以这样做:

public class Consumer

   public readonly string FirstName;
   public readonly string LastName;

   public Consumer(string firstName, string lastName)
   
       this.FirstName = firstName;
       this.LastName = lastName;
   

   public Consumer WithFirstName(string firstName)
     => string.Equals(this.FirstName, firstName) 
              ? this 
              : new Consumer(firstName, this.LastName);

   public Consumer WithLastName(string lastName)
     => string.Equals(this.LastName, lastName)
              ? this
              : new Consumer(this.FirstName, lastName);
   

Related dotnet blogpost

【讨论】:

以上是关于修改/过滤而不改变对象的主要内容,如果未能解决你的问题,请参考以下文章

一次又一次地改变一个 div 内容而不丢失以前的 html

我们如何使用过滤器修改请求对象中的标头

Servlet过滤器

ng-repeat过滤器,在过滤器删除了对象时显示消息

Servlet 过滤器

过滤掉特定值而不排除 NULL 行