基于C# Record实现可区分联合:自研方案对比第三方库的不足探讨
自研C# Record可区分联合方案的疑问
背景与自研方案
为避免在应用层通过抛出异常处理预期错误,我尝试用C# Record实现可区分联合,认为引入第三方库过于冗余,因此自研了如下方案:
public abstract record CreateCustomerResponse { private CreateCustomerResponse() { } public sealed record Success(Customer Customer) : CreateCustomerResponse; public sealed record Error(string Code, string Message) : CreateCustomerResponse, IErrorResponse; public sealed record Unauthorized() : CreateCustomerResponse; }
方案实现与使用
该方案通过抽象密封Record限制类型范围,实现方式与第三方库的可区分联合类似:
static CreateCustomerResponse CreateCustomer(Customer customer) { // Or do data validation however you prefer. if (string.IsNullOrEmpty(customer.FirstName)) return new CreateCustomerResponse.Error(nameof(customer.FirstName), "First name is required"); if (string.IsNullOrEmpty(customer.LastName)) return new CreateCustomerResponse.Error(nameof(customer.LastName), "Last name is required"); return new CreateCustomerResponse.Success(customer); }
且可借助C#模式匹配轻松消费:
static string PrintResponse(CreateCustomerResponse response) { return response switch { CreateCustomerResponse.Success result => $"OK, so {result.Customer.FirstName} was created", CreateCustomerResponse.Error => $"Sorry, operation failed: {response}", CreateCustomerResponse.Unauthorized => "You're unauthorized pal", _ => throw new NotImplementedException() }; }
目前发现仅存在switch表达式无法识别全案例覆盖的小问题,但添加默认分支即可解决。我看到很多人使用OneOf等第三方库实现类似功能,想请教:该自研方案是否存在未考虑到的缺陷?相比第三方库是否遗漏了关键特性?
解答
你的自研方案在简单业务场景下可以正常运行,但对比OneOf这类成熟第三方库,确实存在不少未考虑到的缺陷和特性遗漏:
- 重复代码冗余:每个业务操作都要编写一套独立的抽象Record+密封子类(比如
CreateOrderResponse、UpdateCustomerResponse),大量重复结构会显著增加维护成本;而OneOf通过泛型可直接定义OneOf<Success<Customer>, Error, Unauthorized>,无需重复编写类结构。 - 通用操作缺失:第三方库通常提供了通用的映射、匹配、链式处理方法,比如OneOf的
Match方法可直接链式调用处理结果,还支持Bind、Map等操作组合业务逻辑;自研方案每次都要手动编写switch表达式,无法复用通用逻辑,代码复用性差。 - 编译期全分支覆盖检查缺失:你遇到的switch无法识别全案例覆盖是核心问题——OneOf配合C# Nullable参考类型和静态分析工具,可在编译期强制检查所有分支是否被处理,避免遗漏新的结果类型;而自研方案只能依赖手动添加默认分支,编译期无法保障,后续新增分支时容易出现遗漏。
- 序列化兼容性问题:成熟第三方库已经处理了JSON序列化/反序列化的兼容性,能正确识别不同分支类型并完成序列化;自研方案如果需要跨服务传输结果,可能需要手动编写JsonConverter,否则序列化后无法正确反序列化为对应的子类,增加额外开发成本。
- 扩展性不足:如果后续需要给所有结果添加通用属性(比如请求ID、处理时间戳),自研方案需要修改每个抽象Record类;而第三方库可通过泛型扩展或统一基类批量处理,扩展性更强。
内容的提问来源于stack exchange,提问作者Meryovi
相关产品推荐
相关产品推荐

