为什么以及如何(内部)Enum.IsDefined搜索名称和值?

Far*_*yev 14 .net c# enums enumeration

让我们说我们定义了Planets枚举:

public enum Planets
{
    Sun = 0,
    Mercury=5,          
    Venus,              
    Earth,          
    Jupiter,        
    Uranus,         
    Neptune   
}
Run Code Online (Sandbox Code Playgroud)

我正在使用Enum.IsDefined方法来查找字符串是否存在于枚举中.

Enum.IsDefined(typeof(Planets), "Mercury"); // result is true
Run Code Online (Sandbox Code Playgroud)

但是,然后我尝试了这个,它也返回true:

Enum.IsDefined(typeof(Planets), 5); // result is true again
Run Code Online (Sandbox Code Playgroud)

它是怎么来的?这种方法没有任何过载.它只有一个签名:

Enum.IsDefined(Type enumType, object value);
Run Code Online (Sandbox Code Playgroud)

为什么以及如何Enum.IsDefined搜索名称和价值?这对我来说真的很有趣,为什么他们这样选择?IMO制造超载会是更好的选择,不是吗?

Son*_*nül 11

Enum.IsDefined方法

value参数可以是以下任何一项:

  • 任何类型为enumType的成员.
  • 一个变量,其值是enumType类型的枚举成员.
  • 枚举成员名称的字符串表示形式.字符串中的字符必须与枚举成员名称具有相同的大小写.
  • enumType的基础类型的值.

我相信这就是为什么它没有过载并object作为第二个参数.由于这种方法采用object作为第二个参数-和object为所有.NET类型的基类-可以传递stringint或等.

这里实现了这种方法;

public static bool IsDefined(Type enumType, Object value)
{
     if (enumType == null)
         throw new ArgumentNullException("enumType");                    
     return enumType.IsEnumDefined(value);
}
Run Code Online (Sandbox Code Playgroud)

看起来这个虚Type.IsEnumDefined方法在它的实现中处理所有这些情况;

    public virtual bool IsEnumDefined(object value)
    {
        if (value == null)
            throw new ArgumentNullException("value");

        if (!IsEnum)
            throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
        Contract.EndContractBlock();

        // Check if both of them are of the same type
        Type valueType = value.GetType();

        // If the value is an Enum then we need to extract the underlying value from it
        if (valueType.IsEnum)
        {
            if (!valueType.IsEquivalentTo(this))
                throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType", valueType.ToString(), this.ToString()));

            valueType = valueType.GetEnumUnderlyingType();
        }

        // If a string is passed in
        if (valueType == typeof(string))
        {
            string[] names = GetEnumNames();
            if (Array.IndexOf(names, value) >= 0)
                return true;
            else
                return false;
        }

        // If an enum or integer value is passed in
        if (Type.IsIntegerType(valueType))
        {
            Type underlyingType = GetEnumUnderlyingType();
            // We cannot compare the types directly because valueType is always a runtime type but underlyingType might not be.
            if (underlyingType.GetTypeCodeImpl() != valueType.GetTypeCodeImpl())
                throw new ArgumentException(Environment.GetResourceString("Arg_EnumUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), underlyingType.ToString()));

            Array values = GetEnumRawConstantValues();
            return (BinarySearch(values, value) >= 0);
        }
    }
Run Code Online (Sandbox Code Playgroud)