Diambil dari Confusion dengan mengurai Enum
Ini adalah keputusan dari pihak orang-orang yang membuat .NET. Enum didukung oleh jenis nilai lain ( int, short, byte, dll), dan sehingga benar-benar dapat memiliki nilai yang berlaku untuk jenis-jenis nilai.
Saya pribadi bukan penggemar cara kerjanya, jadi saya membuat serangkaian metode utilitas:
/// <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);
}
}
Dengan cara ini, saya dapat mengatakan:
if(!sEnum.IsDefined()) throw new Exception(...);
... atau:
EnumUtil<Stooge>.Parse(s); // throws an exception if s is not a defined value.
Sunting
Di luar penjelasan yang diberikan di atas, Anda harus menyadari bahwa versi .NET dari Enum mengikuti pola yang lebih terinspirasi C daripada yang terinspirasi oleh Java. Hal ini memungkinkan untuk memiliki enum "Bit Flag" yang dapat menggunakan pola biner untuk menentukan apakah "flag" tertentu aktif dalam nilai enum. Jika Anda harus menentukan setiap kemungkinan kombinasi flag (mis MondayAndTuesday. MondayAndWednesdayAndThursday), Ini akan sangat membosankan. Jadi memiliki kapasitas untuk menggunakan nilai enum yang tidak ditentukan bisa sangat berguna. Ini hanya membutuhkan sedikit kerja ekstra ketika Anda menginginkan perilaku cepat gagal pada jenis enum yang tidak memanfaatkan trik semacam ini.