如果我有一个 C# 枚举,其中两个对象映射到相同的整数值,是否有任何可能的方法来获取每个唯一的
Enum
对象?我尝试过的每种方法仅返回一个对象 - 这可能是该值第一次出现。
假设我定义了以下枚举,其中两个对象由于某种原因映射到相同的整数值。
public enum Testing
{
[Description("This is Value1")]
[Display(Name = "Value 1")]
Value1 = 0,
[Description("This is Value2")]
[Display(Name = "Value 2")]
Value2 = 1,
[Description("This is Value3")]
[Display(Name = "Value 3")]
Value3 = 2,
[Description("This is Value4")]
[Display(Name = "Value 4")]
Value4 = 0
}
在这种情况下,根据某些标准,我需要
Value1
和 Value4
都映射到积分值 0。这两个值的功能将在应用程序中产生相同的行为。这两个选项存在背后的原因不一定相关,但举例来说,我希望用户非常清楚 Value1 和 Value4 都映射到 0,即使它们不一定是相同的选项。
然后我想在运行时动态加载
Testing
类型的枚举对象。对于两个选项不映射到相同整数值的枚举,有很多方法可以做到这一点。使用 Enum.GetValues()
、Enum.GetNames
,使用反射获取 FieldInfo[]
,然后迭代每个并调用 FieldInfo.GetValue()
。这些都正常工作......但是当两个 Enum 对象映射到相同的整数值时,使用任何返回 Enum 对象的方法都会为 Value1
和 Value4
返回相同的对象 - 可能 Value1
.
但是,在本例中,我为每个对象设置了特定属性。我想以允许我在运行时利用这些属性的方式加载对象。也许我想在下拉列表中显示每个选项,并希望使用
Display
属性中的名称来提供更多用户友好的字符串,或者能够在每个选项的工具提示中提供额外的冗长描述。
我尝试了以下方法,但没有效果,它们都会导致返回
Value1
的 Value4
对象,这不可避免地导致访问 Value1
的自定义属性,而不是 Value4
。
foreach (Enum value in Enum.GetValues(type))
{
// value for Value4 is Value1...
}
foreach (string name in Enum.GetNames(type))
{
Enum value = (Enum)Enum.Parse(type, name);
// value for Value4 is Value1...
}
foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Public | BindingFlags.Static))
{
Enum value = (Enum)fieldInfo.GetValue(null);
// value for Value4 is Value1...
// fieldInfo DOES have the custom attributes for Value4 and DOES have the original name Value4
}
在 C# 中是否有任何可能的方法来保留
Value4
的原始枚举对象?从技术上讲,我可以存储 FieldInfo
对象,但我宁愿(并且需要)存储 Enum 对象。我很惊讶,甚至没有通过反射迭代字段信息,我肯定有 Value4
字段也不会返回该对象。
你所要求的是不可能的。一个示例程序可以在这里快速演示该问题:
using System;
public enum ExampleEnum
{
SomeValue = 1,
AliasValue = 1
}
public class Program
{
public static void Main()
{
var x = ExampleEnum.AliasValue;
Console.WriteLine(x.ToString());
}
}
您自然会期望该程序将“AliasValue”写入控制台,但您却看到“SomeValue”。其原因很容易理解 - 枚举在幕后被实现为整数。当从整数返回 Enum 成员时,C# 将只选择第一个具有相应值的成员。 C# 仅保留整数值,如果两个枚举成员具有相同的值,则应假定它们也具有相同的行为。
在这种情况下,根据某些标准,我需要 Value1 和 Value4 都映射到整数值 0。这两个值的功能将在应用程序中产生相同的行为。这两个选项存在背后的原因不一定相关,但举例来说,我希望用户非常清楚 Value1 和 Value4 都映射到 0,即使它们不一定是相同的选项。
我建议您重新考虑这种方法。如果行为没有差异,那么标签是否“自动更正”到第一个选项应该没有关系。如果它确实很重要,那么听起来好像存在有差异,并且它们不应该具有相同的值。
由于仍然存在一些混乱,我将在示例中添加更多内容。您自己不会在整数和枚举之间进行转换,但 C# is 在幕后做类似的事情。它可能会帮助您假设“Enum”只是“整数”类型包装器的语法糖,并且每个成员都转换为“const int”字段:
public record struct ExampleEnum(int value)
{
public static readonly ExampleEnum SomeValue = new(1);
public static readonly ExampleEnum AliasValue = new(1);
public string ToString() => value switch =>
{
1 => "SomeValue",
_ => value.ToString(),
};
}
public class Program
{
public static void Main()
{
var x = ExampleEnum.AliasValue;
Console.WriteLine(x.ToString());
}
}
*这不是完全幕后发生的事情,但它是一个近似值