Entnommen aus der Verwirrung mit dem Parsen einer Aufzählung
Dies war eine Entscheidung der Leute, die .NET erstellt haben. Ein ENUM wird von einem anderen Werttyp gesichert ( int, short, byte, usw.), und so ist es tatsächlich einen beliebigen Wert haben kann , die für die Werttypen gültig ist.
Ich persönlich bin kein Fan der Funktionsweise, daher habe ich eine Reihe von Dienstprogrammmethoden entwickelt:
/// <summary>
/// Utility methods for enum values. This static type will fail to initialize
/// (throwing a <see cref="TypeInitializationException"/>) if
/// you try to provide a value that is not an enum.
/// </summary>
/// <typeparam name="T">An enum type. </typeparam>
public static class EnumUtil<T>
where T : struct, IConvertible // Try to get as much of a static check as we can.
{
// The .NET framework doesn't provide a compile-checked
// way to ensure that a type is an enum, so we have to check when the type
// is statically invoked.
static EnumUtil()
{
// Throw Exception on static initialization if the given type isn't an enum.
Require.That(typeof (T).IsEnum, () => typeof(T).FullName + " is not an enum type.");
}
/// <summary>
/// In the .NET Framework, objects can be cast to enum values which are not
/// defined for their type. This method provides a simple fail-fast check
/// that the enum value is defined, and creates a cast at the same time.
/// Cast the given value as the given enum type.
/// Throw an exception if the value is not defined for the given enum type.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="enumValue"></param>
/// <exception cref="InvalidCastException">
/// If the given value is not a defined value of the enum type.
/// </exception>
/// <returns></returns>
public static T DefinedCast(object enumValue)
{
if (!System.Enum.IsDefined(typeof(T), enumValue))
throw new InvalidCastException(enumValue + " is not a defined value for enum type " +
typeof (T).FullName);
return (T) enumValue;
}
/// <summary>
///
/// </summary>
/// <param name="enumValue"></param>
/// <returns></returns>
public static T Parse(string enumValue)
{
var parsedValue = (T)System.Enum.Parse(typeof (T), enumValue);
//Require that the parsed value is defined
Require.That(parsedValue.IsDefined(),
() => new ArgumentException(string.Format("{0} is not a defined value for enum type {1}",
enumValue, typeof(T).FullName)));
return parsedValue;
}
public static bool IsDefined(T enumValue)
{
return System.Enum.IsDefined(typeof (T), enumValue);
}
}
public static class EnumExtensions
{
public static bool IsDefined<T>(this T enumValue)
where T : struct, IConvertible
{
return EnumUtil<T>.IsDefined(enumValue);
}
}
Auf diese Weise kann ich sagen:
if(!sEnum.IsDefined()) throw new Exception(...);
... oder:
EnumUtil<Stooge>.Parse(s); // throws an exception if s is not a defined value.
Bearbeiten
Über die oben gegebene Erklärung hinaus müssen Sie erkennen, dass die .NET-Version von Enum einem C-inspirierten Muster folgt als einem Java-inspirierten. Dies ermöglicht es, "Bit Flag" -Aufzählungen zu haben, die binäre Muster verwenden können, um zu bestimmen, ob ein bestimmtes "Flag" in einem Aufzählungswert aktiv ist. Wenn Sie jede mögliche Kombination von Flags (dh definieren haben MondayAndTuesday, MondayAndWednesdayAndThursday), würde dies äußerst langwierig sein. Die Fähigkeit, undefinierte Aufzählungswerte zu verwenden, kann also sehr praktisch sein. Es erfordert nur ein wenig zusätzliche Arbeit, wenn Sie ein schnelles Verhalten bei Aufzählungstypen wünschen, die diese Art von Tricks nicht nutzen.