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

C#中Enum.ToString()返回非预期值的原因及解决方法

枚举多成员同值时ToString()返回异常的原因及解决办法

问题原因

在.NET中,枚举类型的实例本质上仅存储对应的整数值,不会记录它是通过哪个成员名称获取的。当多个枚举成员共享同一数值时,ToString()(以及Enum.GetName等名称解析方法)会返回枚举定义中第一个匹配该数值的成员名称(具体顺序取决于.NET对枚举元数据的遍历逻辑)。这就是为什么你调用country.UnitedKingdom.ToString()时返回其他成员名——因为所有这些成员的数值都是1,.NET无法区分你调用的是哪个成员,只能返回它找到的第一个匹配名称。

解决办法

由于你需要同时实现「调用对应成员时返回正确名称」和「字符串转枚举」的需求,推荐以下两种可行方案:

方案1:使用Description特性+扩展方法

给每个枚举成员添加DescriptionAttribute,通过扩展方法读取特性值实现精准的名称解析,同时支持字符串转枚举。

  1. 定义带特性的枚举:
using System.ComponentModel;

public enum Country
{
    [Description("UnitedKingdom")]
    UnitedKingdom = 1,
    [Description("Wales")]
    Wales = 1,
    [Description("England")]
    England = 1,
    [Description("Scotland")]
    Scotland = 1
}
  1. 编写枚举扩展方法:
using System;
using System.ComponentModel;
using System.Reflection;

public static class EnumExtensions
{
    // 获取枚举成员的自定义名称(优先取Description,无则返回成员名)
    public static string GetEnumName(this Enum enumValue)
    {
        FieldInfo fieldInfo = enumValue.GetType().GetField(enumValue.ToString());
        DescriptionAttribute descAttr = fieldInfo?.GetCustomAttribute<DescriptionAttribute>();
        return descAttr?.Description ?? enumValue.ToString();
    }

    // 字符串转枚举,支持匹配成员名或Description
    public static T ParseToEnum<T>(string input) where T : Enum
    {
        foreach (FieldInfo field in typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static))
        {
            DescriptionAttribute descAttr = field.GetCustomAttribute<DescriptionAttribute>();
            if (string.Equals(field.Name, input, StringComparison.OrdinalIgnoreCase) ||
                string.Equals(descAttr?.Description, input, StringComparison.OrdinalIgnoreCase))
            {
                return (T)field.GetValue(null);
            }
        }
        throw new ArgumentException($"无法将字符串\"{input}\"转换为枚举{typeof(T).Name}");
    }
}
  1. 使用示例:
// 获取正确名称
string ukName = Country.UnitedKingdom.GetEnumName(); // 返回"UnitedKingdom"
string walesName = Country.Wales.GetEnumName(); // 返回"Wales"

// 字符串转枚举
Country uk = EnumExtensions.ParseToEnum<Country>("UnitedKingdom");
Country scotland = EnumExtensions.ParseToEnum<Country>("Scotland");

方案2:使用字典映射(无需特性)

直接定义字典存储枚举成员与名称的映射,逻辑更直观,适合枚举成员较少的场景。

  1. 定义枚举(无需特性):
public enum Country
{
    UnitedKingdom = 1,
    Wales = 1,
    England = 1,
    Scotland = 1
}
  1. 编写映射及扩展方法:
using System;
using System.Collections.Generic;
using System.Linq;

public static class CountryExtensions
{
    private static readonly Dictionary<Country, string> _countryToName = new Dictionary<Country, string>
    {
        { Country.UnitedKingdom, "UnitedKingdom" },
        { Country.Wales, "Wales" },
        { Country.England, "England" },
        { Country.Scotland, "Scotland" }
    };

    private static readonly Dictionary<string, Country> _nameToCountry = 
        _countryToName.ToDictionary(kv => kv.Value, kv => kv.Key, StringComparer.OrdinalIgnoreCase);

    // 获取枚举成员对应名称
    public static string GetName(this Country country)
    {
        return _countryToName.TryGetValue(country, out string name) ? name : country.ToString();
    }

    // 字符串转枚举
    public static Country Parse(string input)
    {
        return _nameToCountry.TryGetValue(input, out Country country) ? country 
            : throw new ArgumentException($"无效的国家名称:{input}");
    }
}
  1. 使用示例:
string englandName = Country.England.GetName(); // 返回"England"
Country wales = CountryExtensions.Parse("Wales");

内容的提问来源于stack exchange,提问作者Mr Fivian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 17:42:25