C#中XmlSerializer默认将枚举序列化为字符串名称而非数值,需确保枚举及属性为public、不使用[Flags],配合[XmlEnum]可自定义名称;DataContractSerializer则需[DataContract]和[EnumMember]。

C#中将枚举序列化为XML,默认情况下会输出枚举的**数值(int)**,而不是名称。若想让XML中显示枚举的**字符串名称**(如 [XmlEnum] 或 [EnumMember] 特性,并选择合适的序列化器。
使用 XmlSerializer 序列化为名称(推荐)
XmlSerializer 支持通过 [XmlEnum] 特性控制枚举成员在XML中的显示名称。它默认就序列化为名称(而非数值),前提是枚举直接作为类的公共字段/属性参与序列化。
- 给枚举成员添加
[XmlEnum("自定义名")]可重命名;不加则用原名称 - 确保枚举类型是 public,且被序列化的类中该属性是 public 且有 get/set
- 不要用
[Flags]枚举(位组合)直接序列化,否则结果不可靠
示例:
public enum UserStatus
{
[XmlEnum("inactive")]
Inactive = 0,
[XmlEnum("active")]
Active = 1,
[XmlEnum("pending")]
Pending = 2
}
public class User
{
public string Name { get; set; }
public UserStatus Status { get; set; }
}
// 序列化
var user = new User { Name = "Alice", Status = UserStatus.Active };
var serializer = new XmlSerializer(typeof(User));
serializer.Serialize(Console.Out, user);
// 输出:Alice active
避免数值序列化(常见陷阱)
如果没加任何特性,且使用 XmlSerializer,它仍会输出名称——但容易误以为输出的是数值,其实是默认行为。真正输出数值的是以下情况:
- 手动调用
ToString("D")或(int)enumValue后再序列化 - 用
DataContractSerializer且未标记[EnumMember] - 把枚举转成 int 再塞进 XML 模型里
所以关键不是“怎么改成名称”,而是“别意外转成数值”。只要用 XmlSerializer + 公共属性 + 默认枚举,就自然输出名称。
需要兼容 DataContractSerializer?用 [EnumMember]
若项目统一用 DataContractSerializer(如 WCF、旧版 Web API),则需配合 [DataContract] 和 [EnumMember]:
- 枚举类型加
[DataContract] - 每个成员加
[EnumMember(Value = "xxx")](Value 可选,不写则用名称) - 注意:此时必须所有成员都显式标记,否则未标记的成员会被忽略
[DataContract]
public enum OrderState
{
[EnumMember(Value = "draft")]
Draft = 1,
[EnumMember(Value = "confirmed")]
Confirmed = 2
}
反序列化也自动匹配名称
无论是 XmlSerializer 还是 DataContractSerializer,只要XML中写的是名称(如 ),反序列化时都能正确还原为对应枚举值,无需额外配置。
- 大小写敏感:默认严格匹配(
Active≠active) - 可借助
XmlSerializer.Deserialize的异常信息快速定位拼写错误 - 如需忽略大小写,需自定义
XmlSerializationReader(极少需要)










