为何无法将YAML反序列化为C# record类型?
YamlDotNet无法反序列化C#引用类型record的原因及解决办法
问题重现
你遇到的问题是:使用YamlDotNet将YAML反序列化为C#引用类型record时抛出序列化异常,但record struct、普通struct、带get/init属性的类都能正常反序列化。错误信息如下:
Unhandled exception. (Line: 2, Col: 3, Idx: 9) - (Line: 2, Col: 3, Idx: 9): Exception during deserialization
核心原因
C#引用类型record与record struct、普通类的核心差异在于构造逻辑:
- 引用类型
record默认会生成主构造函数,编译器会自动生成基于主构造函数参数的属性初始化逻辑,但不会自动生成无参构造函数(除非显式定义)。 - YamlDotNet的默认反序列化器优先尝试用无参构造函数实例化对象,再赋值属性;如果找不到无参构造函数,也没有明确指定要使用的构造函数,就会触发序列化异常。
- 而
record struct、普通struct会默认生成无参构造函数;带get/init的类如果没有自定义构造函数,编译器也会自动生成无参构造函数,因此能被正常处理。
解决办法
1. 显式为record添加无参构造函数
在引用类型record中手动定义无参构造函数,让YamlDotNet可以正常实例化对象:
public record User(string Name, int Age) { // 显式添加无参构造函数,委托给主构造函数初始化默认值 public User() : this(string.Empty, 0) { } }
2. 标记YamlDotNet使用主构造函数反序列化
通过[YamlConstructor]属性指定反序列化时使用record的主构造函数,让YamlDotNet直接通过构造函数参数完成初始化:
public record User { public string Name { get; init; } public int Age { get; init; } // 标记该构造函数为反序列化使用的构造函数 [YamlConstructor] public User(string name, int age) { Name = name; Age = age; } }
如果是简洁写法的record,可配合YamlMember属性精准映射YAML字段与构造参数:
public record User( [property: YamlMember(Alias = "name")] string Name, [property: YamlMember(Alias = "age")] int Age );
3. 升级YamlDotNet到最新版本
较旧版本的YamlDotNet对C# record的支持不完善,升级到13.x及以上的最新稳定版后,对引用类型record的处理逻辑已优化,可能无需额外修改即可正常反序列化。
内容的提问来源于stack exchange,提问作者BlueStaggo
相关产品推荐
相关产品推荐

