You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让C#中的with表达式支持类类型?

类类型实现类似with表达式的替代方案

C#原生的with表达式仅支持记录类型(record)和结构体(struct),普通类无法直接使用,会触发CS8858编译错误。针对大量数据对象、不愿逐个添加复制构造函数的场景,可通过以下方式实现类似“复制对象并修改指定成员”的功能:

1. 通用扩展方法封装克隆+修改逻辑

写一个通用扩展方法,结合序列化或反射实现克隆,再链式执行修改操作,语法接近with:

using System.Text.Json;

public static class ObjectExtensions
{
    // 基于Json序列化的浅克隆实现,可按需替换为深克隆逻辑
    public static T With<T>(this T source, Action<T> modify) where T : class
    {
        if (source == null) throw new ArgumentNullException(nameof(source));
        
        var clone = JsonSerializer.Deserialize<T>(JsonSerializer.Serialize(source));
        modify(clone);
        return clone;
    }
}

// 使用示例
var copy = someInstance.With(x => 
{
    x.SomeProperty = "newValue";
    x.AnotherProperty = 123;
});

注意:这种方式是浅克隆,如果对象包含引用类型成员,需要调整为深克隆(比如修改Json序列化配置,或改用反射遍历成员复制)。

2. 结合映射器简化代码

如果已经在使用AutoMapper等映射工具,可以通过映射器的配置实现更简洁的写法:

// 方式1:使用AfterMap回调
var copy = Mapper.Map<SomeClass>(someInstance, opt => 
    opt.AfterMap((_, dest) => dest.SomeProperty = "newValue")
);

// 方式2:结合匿名类型(若映射器支持从匿名类型映射)
var copy = Mapper.Map<SomeClass>(new 
{ 
    someInstance.Property, 
    SomeProperty = "newValue" 
});

3. 为类添加自定义的With系列方法

如果是自己维护的类,可以针对性编写类型安全的WithXXX方法,性能比序列化更好:

public class SomeClass
{
    public string Property { get; set; }
    public string SomeProperty { get; set; }
    public int AnotherProperty { get; set; }

    // 复制当前实例并修改指定属性
    public SomeClass WithSomeProperty(string value)
    {
        return new SomeClass
        {
            Property = this.Property,
            AnotherProperty = this.AnotherProperty,
            SomeProperty = value
        };
    }

    // 支持链式调用多个修改
    public SomeClass WithAnotherProperty(int value)
    {
        return new SomeClass
        {
            Property = this.Property,
            SomeProperty = this.SomeProperty,
            AnotherProperty = value
        };
    }
}

// 使用示例
var copy = someInstance.WithSomeProperty("newValue").WithAnotherProperty(456);

这种方式类型安全、性能最优,但需要为每个常用的修改场景编写对应方法,适合高频修改的类。

4. 源生成器自动生成克隆代码

可以借助C#源生成器,在编译时自动为类生成类似记录的with功能代码。比如自定义一个SupportsWithAttribute,然后编写源生成器扫描标记了该属性的类,自动生成包含克隆+修改逻辑的扩展方法,实现和原生with几乎一致的语法体验。


内容的提问来源于stack exchange,提问作者Jeff Mercado

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 04:35:26