Все перечисления должны использовать один из следующих типов в своем заявлении: 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()));
}
}
(Incidently, метод Enum.GetUnderlyingType
, кажется, один вы искали, но он никогда не возвращается char
, потому что вы не можете иметь полукокс перечислений на языке)
Это позволит вам добраться до расширенного понятия полукокса перечислений:.
var value3 = EnumEx.ConvertToUnderlyingType(MyEnum2.Value3);
Console.WriteLine(value3);
Это напечатает c
на консоли.
Обратите внимание на базовый тип и значения ваших перечислений символов, они должны идеально вписываться в char
, чтобы избежать ошибок преобразования (переполнения). Безопасные типы - 16-разрядные (как и char
) или менее: byte
, sbyte
, short
или ushort
. Другие типы в порядке, если значения в перечислении могут быть преобразованы в 16-разрядные символы без потери точности (как в примере выше).
Использование стандартных (int
) базового типа и символов символов в качестве значений перечисления (которые неявно конвертируются в int
) является достаточно хорошим.
UPDATE:
Вы можете объявить обугленного перечисление в 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());
дает ошибку компилятора:
error CS0570: 'Drawing.Color.Red' is not supported by the language
В VB.NET нет никакой ошибки компиляции, но есть ошибка времени выполнения от Enum.GetName
. Похоже, что время выполнения не готово к работе с перечислениями символов. Это отрывок из этого метода (с отражателем):
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");
}
Он проверяет не только то, что тип является перечисление, но он также является одним из указанных выше основных типов (для которых символ не вариант) , Таким образом, вы действительно не должны создавать char enums в F #. Вы можете использовать описанный мной подход «расширения».
Это и заключение, к которому я пришел. Я понял, что C# рассматривал его как целое, независимо от того, но мне нужен был кто-то, чтобы подтвердить это для меня. Спасибо :) –
@Nathan: Я отредактировал ответ, чтобы включить немного больше. В принципе, у вас не может быть базового типа char. –