Все перечисления должны использовать в своем объявлении один из следующих типов: byte
, sbyte
, short
, ushort
, int
, uint
, long
или ulong
.Вот как вы указываете тип:
enum MyEnum3 : long {
Value1 = 5L,
Value2 = 9L,
Value3 = long.MaxValue
}
Если вы не укажете тип, по умолчанию будет int
.
К сожалению, вы не можете указать char
какбазовый тип.Вы можете создать это «расширение» в качестве пользовательского атрибута:
[AttributeUsage(AttributeTargets.Enum)]
public class CharAttribute : Attribute { }
[Char] enum MyEnum2 {
Value1 = 'a',
Value2 = 'b',
Value3 = 'c'
}
И затем иметь такой класс:
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()));
}
}
(Кстати, метод Enum.GetUnderlyingType
, кажется, тот, который вы искали, но он никогда не возвращает char
, потому что у вас не может быть перечислений в языке.)
Это позволит вам получить более широкое представление о символеenums:
var value3 = EnumEx.ConvertToUnderlyingType(MyEnum2.Value3);
Console.WriteLine(value3);
Это выведет c
на консоль.
Обратите внимание на базовый тип и значения ваших символов, они должны идеально вписываться в char
чтобы избежать сбоев преобразования (переполнения).Безопасные типы имеют ширину 16 бит (как char
) или меньше: byte
, sbyte
, short
или ushort
.Другие типы в порядке, если значения в перечислении могут быть преобразованы в 16-битные символы без потери точности (как в примере выше).
Использование стандартного (int
) базового типа и литералов в качестве значений перечисления (которые неявно преобразуются в int
) достаточно.
ОБНОВЛЕНИЕ:
Вы можете объявить перечисление в F #:
namespace Drawing
type Color =
| Red = 'r'
| Green = 'g'
| Blue = 'b'
В C # вы можете использовать его следующим образом:
Console.WriteLine(Enum.GetUnderlyingType(typeof(Color)));
И он напечатает System.Char
.
Но ... C # будет жаловаться, если вы попытаетесь использовать его значения.Это:
Console.WriteLine(Color.Red.ToString());
Выдает ошибку компилятора:
Ошибка CS0570: «Drawing.Color.Red» не поддерживается языком
В VB.NET нет ошибки компиляции, но есть ошибка времени выполнения от Enum.GetName
.Похоже, что среда выполнения не готова работать с перечислениями.Вот выдержка из этого метода (из 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");
}
Он проверяет не только то, что тип является перечислением, но и то, что он также является одним из вышеупомянутых базовых типов (для которых символ не являетсяопция). Так что вы действительно не должны создавать перечисления в F #. Вы можете использовать подход «расширения», который я описал.