考虑以下两个枚举:
enum MyEnum1 {
Value1 = 1,
Value2 = 2,
Value3 = 3
}
enum MyEnum2 {
Value1 = 'a',
Value2 = 'b',
Value3 = 'c'
}
Run Code Online (Sandbox Code Playgroud)
我可以通过显式转换来检索由这些枚举值表示的物理值,((int)MyEnum1.Value2) == 2或者((char)MyEnum2.Value2) == 'b',但是如果我想在不首先知道要转换的类型的情况下获取char表示或int表示,该怎么办?
是否有可能在没有强制转换的情况下获取枚举的基础值,或者至少在编程上可以确定基础值的正确类型?
Jon*_*eet 12
这两个枚举的基本价值是int.你仅仅使用一个事实,即有从隐式转换char到int在第二种情况下.
例如,如果你看一下Reflector中的第二个枚举,你会看到如下内容:
internal enum MyEnum2
{
Value1 = 0x61,
Value2 = 0x62,
Value3 = 0x63
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果你想要一个不同的底层类型,你必须指定它,例如
public enum Foo : long
{
}
Run Code Online (Sandbox Code Playgroud)
然而,只有byte,sbyte,short,ushort,int,uint,long,和ulong是有效的基础枚举类型.
:所有枚举必须在其声明中使用下列类型之一
byte,sbyte,short,ushort,int,uint,long或ulong.这是您指定类型的方式:
enum MyEnum3 : long {
Value1 = 5L,
Value2 = 9L,
Value3 = long.MaxValue
}
Run Code Online (Sandbox Code Playgroud)
如果未指定类型,则默认为int.
遗憾的是,您无法指定char为基础类型.您可以将"扩展名"创建为自定义属性:
[AttributeUsage(AttributeTargets.Enum)]
public class CharAttribute : Attribute { }
[Char] enum MyEnum2 {
Value1 = 'a',
Value2 = 'b',
Value3 = 'c'
}
Run Code Online (Sandbox Code Playgroud)
然后有一个这样的类:
public static class EnumEx {
public static Type GetUnderlyingType(Type enumType) {
if (!enumType.IsEnum) throw new ArgumentException();
if (enumType.GetCustomAttributes(typeof(CharAttribute), false).Length > 0) {
return typeof(char);
}
return Enum.GetUnderlyingType(enumType);
}
public static object ConvertToUnderlyingType(object enumValue) {
return Convert.ChangeType(enumValue,
GetUnderlyingType(enumValue.GetType()));
}
}
Run Code Online (Sandbox Code Playgroud)
(很明显,该方法Enum.GetUnderlyingType似乎是您正在寻找的方法,但它永远不会返回,char因为您不能使用该语言中的char枚举.)
这将使您能够获得扩展的char枚举概念:
var value3 = EnumEx.ConvertToUnderlyingType(MyEnum2.Value3);
Console.WriteLine(value3);
Run Code Online (Sandbox Code Playgroud)
这将打印c到控制台.
注意底层类型和char枚举的值,理想情况下它们应该适合char避免转换失败(溢出).安全类型是16位宽(就像char)以下:byte,sbyte,short或ushort.如果枚举中的值可以转换为16位字符而不会丢失精度,则其他类型都可以(就像上面的示例中一样).
使用default(int)底层类型和char文字作为枚举值(可隐式转换为int)就足够了.
更新:
您可以在F#中声明一个char枚举:
namespace Drawing
type Color =
| Red = 'r'
| Green = 'g'
| Blue = 'b'
Run Code Online (Sandbox Code Playgroud)
在C#中,您可以像这样使用它:
Console.WriteLine(Enum.GetUnderlyingType(typeof(Color)));
Run Code Online (Sandbox Code Playgroud)
它会打印出来System.Char.
但是......如果你试图使用它的值,C#会抱怨.这个:
Console.WriteLine(Color.Red.ToString());
Run Code Online (Sandbox Code Playgroud)
给出编译器错误:
错误CS0570:语言不支持'Drawing.Color.Red'
在VB.NET中没有编译错误,但是存在运行时错误Enum.GetName.似乎运行时没有准备好处理char枚举.这是该方法的摘录(来自Reflector):
if (((!type.IsEnum && (type != intType)) && ((type != typeof(short)) && (type != typeof(ushort)))) && (((type != typeof(byte)) && (type != typeof(sbyte))) && (((type != typeof(uint)) && (type != typeof(long))) && (type != typeof(ulong)))))
{
throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
}
Run Code Online (Sandbox Code Playgroud)
它不仅检查类型是枚举,还检查它是上述基础类型之一(char不是一个选项).所以你真的不应该在F#中创建char枚举.您可以使用我所描述的"扩展"方法.
| 归档时间: |
|
| 查看次数: |
6160 次 |
| 最近记录: |