Alle Enums müssen einen der folgenden Typen in ihrer Deklaration verwenden: byte
, sbyte
, short
, ushort
, int
, uint
, long
o ulong
. So geben Sie einen Typ an:
enum MyEnum3 : long {
Value1 = 5L,
Value2 = 9L,
Value3 = long.MaxValue
}
Wenn Sie keinen Typ angeben, ist der Standardwert int
.
Leider können Sie nicht angeben char
als zugrunde liegender Typ. Sie könnten diese "Erweiterung" als benutzerdefiniertes Attribut erstellen:
[AttributeUsage(AttributeTargets.Enum)]
public class CharAttribute : Attribute { }
[Char] enum MyEnum2 {
Value1 = 'a',
Value2 = 'b',
Value3 = 'c'
}
Und dann eine Klasse wie diese:
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()));
}
}
(Nebenbei bemerkt, die Methode Enum.GetUnderlyingType
scheint das Gesuchte zu sein, aber es kommt nicht zurück char
weil man in der Sprache keine Char-Enums haben kann).
Auf diese Weise können Sie zu Ihrem erweiterten Begriff von char enums gelangen:
var value3 = EnumEx.ConvertToUnderlyingType(MyEnum2.Value3);
Console.WriteLine(value3);
Damit wird gedruckt c
an die Konsole.
Achten Sie auf den zugrundeliegenden Typ und die Werte Ihrer Char-Enums, sie sollten idealerweise in eine char
zur Vermeidung von Konvertierungsfehlern (Überläufen). Die sicheren Typen sind 16 Bit breit (genau wie char
) oder weniger: byte
, sbyte
, short
o ushort
. Andere Typen sind in Ordnung, wenn die Werte in der Aufzählung ohne Präzisionsverlust in 16-Bit-Zeichen umgewandelt werden können (wie im obigen Beispiel).
Die Verwendung der Standardeinstellung ( int
) zugrundeliegenden Typ und Char-Literale als Enum-Werte (die implizit konvertierbar sind in int
) ist gut genug.
UPDATE :
Sie können ein char enum in F# deklarieren:
namespace Drawing
type Color =
| Red = 'r'
| Green = 'g'
| Blue = 'b'
In C# können Sie es wie folgt verwenden:
Console.WriteLine(Enum.GetUnderlyingType(typeof(Color)));
Und es wird gedruckt System.Char
.
Aber ... C# wird sich beschweren, wenn Sie versuchen, seine Werte zu verwenden. Dies:
Console.WriteLine(Color.Red.ToString());
Ergibt einen Compilerfehler:
Fehler CS0570: 'Drawing.Color.Red' wird von der Sprache nicht unterstützt
In VB.NET gibt es keinen Kompilierungsfehler, aber es gibt einen Laufzeitfehler von Enum.GetName
. Es scheint, dass die Laufzeitumgebung nicht darauf vorbereitet ist, mit Char-Enums umzugehen. Dies ist ein Auszug aus dieser Methode (aus 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");
}
Es wird nicht nur geprüft, ob der Typ ein Enum ist, sondern auch, ob es sich um einen der oben genannten zugrundeliegenden Typen handelt (für die char keine Option ist). Sie sollten also in F# keine Char-Enums erstellen. Sie könnten den von mir beschriebenen Ansatz der "Erweiterung" verwenden.