验证枚举值

12 个答案:

`IsDefined`适用于大多数情况，您可以从：

``````public static bool TryParseEnum<TEnum>(this int enumValue, out TEnum retVal)
{
retVal = default(TEnum);
bool success = Enum.IsDefined(typeof(TEnum), enumValue);
if (success)
{
retVal = (TEnum)Enum.ToObject(typeof(TEnum), enumValue);
}
return success;
}
``````

（如果你不认为这是一个合适的int扩展，显然只需删除'this'）

<强> WHY

<强> WHERE

<强> RESULT

``````public const MyEnum MYENUM_MINIMUM = MyEnum.One;
public const MyEnum MYENUM_MAXIMUM = MyEnum.Four;

public enum MyEnum
{
One,
Two,
Three,
Four
};

public static MyEnum Validate(MyEnum value)
{
if (value < MYENUM_MINIMUM) { return MYENUM_MINIMUM; }
if (value > MYENUM_MAXIMUM) { return MYENUM_MAXIMUM; }
return value;
}
``````

<强>性能

``````public static T Clamp<T>(T value)
{
int minimum = Enum.GetValues(typeof(T)).GetLowerBound(0);
int maximum = Enum.GetValues(typeof(T)).GetUpperBound(0);

if (Convert.ToInt32(value) < minimum) { return (T)Enum.ToObject(typeof(T), minimum); }
if (Convert.ToInt32(value) > maximum) { return (T)Enum.ToObject(typeof(T), maximum); }
return value;
}
``````

Enum.IsDefined = 1,800,000个刻度

``````public static T ValidateItem<T>(T eEnumItem)
{
if (Enum.IsDefined(typeof(T), eEnumItem) == true)
return eEnumItem;
else
return default(T);
}
``````

System.Enum使用强制转换转换Int32 = 1,800,000个刻度

``````public static Enum Clamp(this Enum value, Enum minimum, Enum maximum)
{
if (Convert.ToInt32(value) < Convert.ToInt32(minimum)) { return minimum; }
if (Convert.ToInt32(value) > Convert.ToInt32(maximum)) { return maximum; }
return value;
}
``````

if（）最小/最大常数 = 43,000 ticks =赢家42x，快316倍。

``````public static MyEnum Clamp(MyEnum value)
{
if (value < MYENUM_MINIMUM) { return MYENUM_MINIMUM; }
if (value > MYENUM_MAXIMUM) { return MYENUM_MAXIMUM; }
return value;
}
``````

-eol -

``````int userInput = 4;
// below, Enum.GetValues converts enum to array. We then convert the array to hashset.
HashSet<int> validVals = new HashSet<int>((int[])Enum.GetValues(typeof(MyEnum)));
// the following could be in a loop, or do multiple comparisons, etc.
if (validVals.Contains(userInput))
{
// is valid
}
``````

Brad Abrams在帖子The Danger of Oversimplification中特别警告 `Enum.IsDefined`

``````public abstract class EnumValidator<TEnum> where TEnum : struct, IConvertible
{
protected static bool IsContiguous
{
get
{
int[] enumVals = Enum.GetValues(typeof(TEnum)).Cast<int>().ToArray();

int lowest = enumVals.OrderBy(i => i).First();
int highest = enumVals.OrderByDescending(i => i).First();

return !Enumerable.Range(lowest, highest).Except(enumVals).Any();
}
}

public static EnumValidator<TEnum> Create()
{
if (!typeof(TEnum).IsEnum)
{
throw new ArgumentException("Please use an enum!");
}

return IsContiguous ? (EnumValidator<TEnum>)new ContiguousEnumValidator<TEnum>() : new JumbledEnumValidator<TEnum>();
}

public abstract bool IsValid(int value);
}

public class JumbledEnumValidator<TEnum> : EnumValidator<TEnum> where TEnum : struct, IConvertible
{

public JumbledEnumValidator()
{
_values = Enum.GetValues(typeof (TEnum)).Cast<int>().ToArray();
}

public override bool IsValid(int value)
{
return _values.Contains(value);
}
}

public class ContiguousEnumValidator<TEnum> : EnumValidator<TEnum> where TEnum : struct, IConvertible
{

public ContiguousEnumValidator()
{
List<int> enumVals = Enum.GetValues(typeof (TEnum)).Cast<int>().ToList();

_lowest = enumVals.OrderBy(i => i).First();
_highest = enumVals.OrderByDescending(i => i).First();
}

public override bool IsValid(int value)
{
return value >= _lowest && value <= _highest;
}
}
``````

``````//Pre import-loop
EnumValidator< MyEnum > enumValidator = EnumValidator< MyEnum >.Create();
while(import)   //Tight RT loop.
{
bool isValid = enumValidator.IsValid(theValue);
}
``````

``````public static TEnum ParseEnum<TEnum>(string valueString, string parameterName = null)
{
var parsed = (TEnum)Enum.Parse(typeof(TEnum), valueString, true);
decimal d;
if (!decimal.TryParse(parsed.ToString(), out d))
{
return parsed;
}

if (!string.IsNullOrEmpty(parameterName))
{
throw new ArgumentException(string.Format("Bad parameter value. Name: {0}, value: {1}", parameterName, valueString), parameterName);
}
else
{
throw new ArgumentException("Bad value. Value: " + valueString);
}
}
``````

``````(ENUMTYPE)Enum.ToObject(typeof(ENUMTYPE), INT)
``````

``````public class EnumValidator<TEnum> : AbstractValidator<TEnum> where TEnum : struct, IConvertible, IComparable, IFormattable
{
public EnumValidator(string message)
{
RuleFor(a => a).Must(a => typeof(TEnum).IsEnum).IsInEnum().WithMessage(message);
}

}
``````

`````` public class Customer
{
public string Name { get; set; }
}
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Town { get; set; }
public string County { get; set; }
public string Postcode { get; set; }
``````

}

``````public enum AddressType
{
HOME,
WORK
}
``````

``````public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
}
}
``````

``````public static class EnumHelpers
{
/// <summary>
/// Returns whether the given enum value is a defined value for its type.
/// </summary>
public static bool IsDefined<T>(this T enumValue)
where T : Enum
=> EnumValueCache<T>.DefinedValues.Contains(enumValue);

/// <summary>
/// Caches the defined values for each enum type for which this class is accessed.
/// </summary>
private static class EnumValueCache<T>
where T : Enum
{
public static HashSet<T> DefinedValues { get; } = new HashSet<T>((T[])Enum.GetValues(typeof(T)));
}
}
``````

``````if (myEnumValue.IsDefined())
// ...
``````

``````public static class EnumHelpers
{
/// <summary>
/// Returns whether the given enum value is a defined value for its type.
/// Throws if the type parameter is not an enum type.
/// </summary>
public static bool IsDefined<T>(T enumValue)
{
if (typeof(T).BaseType != typeof(System.Enum)) throw new ArgumentException(\$"{nameof(T)} must be an enum type.");

return EnumValueCache<T>.DefinedValues.Contains(enumValue);
}

/// <summary>
/// Statically caches each defined value for each enum type for which this class is accessed.
/// Uses the fact that static things exist separately for each distinct type parameter.
/// </summary>
internal static class EnumValueCache<T>
{
public static HashSet<T> DefinedValues { get; }

static EnumValueCache()
{
if (typeof(T).BaseType != typeof(System.Enum)) throw new Exception(\$"{nameof(T)} must be an enum type.");

DefinedValues = new HashSet<T>((T[])System.Enum.GetValues(typeof(T)));
}
}
}
``````

``````public enum DogBreed
{
Unknown = 0,
Beagle = 1,
PeruvianIncaOrchid = 3,
}
public static class DogBreedExtensions
{
public static bool IsValidDogBreed(this DogBreed breed)
{
var v = (int)breed;
return v >= 1 && v <= 3;
}
}
``````

``````var goodInput = 2;
var goodDog = (DogBreed)goodInput;
goodDog.IsValidDogBreed(); // true.

badDog.IsValidDogBreed(); // false, you're in the doghouse!
``````

``````int value = 99;//Your int value
if (Enum.IsDefined(typeof(your_enum_type), value))
{
//Todo when value is valid
}else{
//Todo when value is not valid
}
``````