为什么铸造INT无效枚举值不会抛出异常? [英] Why does casting int to invalid enum value NOT throw exception?
问题描述
如果我有一个枚举,像这样:
If I have an enum like so:
enum Beer
{
Bud = 10,
Stella = 20,
Unknown
}
为什么投放时,它不会抛出异常的 INT
就是这些价值观以外的一种类型啤酒
?
Why does it not throw an exception when casting an int
that is outside of these values to a type of Beer
?
例如下面的code不抛出异常,它输出50到控制台:
For example the following code doesn't throw an exception, it outputs '50' to the console:
int i = 50;
var b = (Beer) i;
Console.WriteLine(b.ToString());
我发现这种奇怪......任何人都可以澄清?
I find this strange...can anyone clarify?
推荐答案
从<一个拍摄href=\"http://stackoverflow.com/questions/4892548/confusion-with-parsing-an-enum/4892571#4892571\">Confusion与解析枚举
这是对谁创建.NET人民的一部分的决定。枚举被另一个值类型的支持( INT
,短
,字节
等),所以它实际上可以具有适用于那些值类型的任何值。
This was a decision on the part of the people who created .NET. An enum is backed by another value type (int
, short
, byte
, etc), and so it can actually have any value that is valid for those value types.
我个人没有这种工作方式的风扇,所以我做了一系列的实用方法:
I personally am not a fan of the way this works, so I made a series of utility methods:
/// <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);
}
}
这样的话,我只能说:
This way, I can say:
if(!sEnum.IsDefined()) throw new Exception(...);
...或者:
EnumUtil<Stooge>.Parse(s); // throws an exception if s is not a defined value.
修改
除了上面给出的解释,你必须认识到,枚举的.NET版本如下比Java的灵感之一更多的C风格的图案。这使得能够有<一个href=\"http://msdn.microsoft.com/en-us/library/cc138362.aspx#192aa3c9-51ce-4882-8f10-af7500e99591\">\"Bit旗枚举可以使用二进制模式来确定特定无论旗帜是在枚举值有效。如果你必须定义标志的每一个可能的组合(即 MondayAndTuesday
, MondayAndWednesdayAndThursday
),这将是非常乏味的,所以不必使用未定义的枚举值可以非常方便的能力。它只是需要当你需要一点额外的工作一个快速失败行为在不利用这些各种各样的把戏枚举类型。
Edit
Beyond the explanation given above, you have to realize that the .NET version of Enum follows a more C-inspired pattern than a Java-inspired one. This makes it possible to have "Bit Flag" enums which can use binary patterns to determine whether a particular "flag" is active in an enum value. If you had to define every possible combination of flags (i.e. MondayAndTuesday
, MondayAndWednesdayAndThursday
), these would be extremely tedious. So having the capacity to use undefined enum values can be really handy. It just requires a little extra work when you want a fail-fast behavior on enum types that don't leverage these sorts of tricks.
这篇关于为什么铸造INT无效枚举值不会抛出异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!