为什么typeof(System.Enum).IsEnum = false?

时间:2014-04-10 11:13:15

标签: c# .net enums

我们知道System.Enum是所有枚举的基础,但我想知道为什么反思说它本身不是枚举?

Console.WriteLine(typeof(System.Enum).IsEnum) // says it is false

我无法理解逻辑,所以System.Enum不是enum,但是从它派生的所有内容都是enum?

当我在msdn看到它是一个类

时,我感到震惊
public abstract class Enum : ValueType, 
    IComparable, IFormattable, IConvertible

所以Enum是一个类,但它是值类型(派生自特殊的ValueType类,它使枚举成为值类型)并且是所有枚举的基础,但不是枚举本身:)

好吧,如果你不相信Enum上课,请检查typeof(System.Enum).IsClass

问题是:是否有任何理由为IsEnum为假,IsClass对于值类型且对所有枚举都是基类的类型为真?

enum AAA { }
typeof(System.Enum).IsClass //True
typeof(System.Enum).IsEnum  //False
typeof(AAA).IsClass         //False
typeof(AAA).IsEnum          //True
typeof(AAA).BaseType        //System.Enum

2 个答案:

答案 0 :(得分:9)

IL不知道结构。 IL只有课程。

那么,什么是C#结构?它是一个密封的类,扩展了System.ValueType类型。 System.ValueType也决定IsClass类的IsStructType属性返回的内容。

那么为什么Type.IsClass会返回false?其实很简单。虽然Type.IsClass实际上会为枚举返回false,但您获得的类型为typeof(Enum)System.Type实际上不是System.RuntimeType - 它是System.RuntimeType。并且IsValueTypeImplreturn !(this == typeof(ValueType)) && !(this == typeof(Enum)) && this.IsSubclassOf(typeof(ValueType)); 方法的定义略有不同:

Enum

因此有一个明确的额外检查 - ValueType类型本身,而从struct派生,因此在语义上为System.Enum,实际上归类为而不是值型。

但是从ValueType派生的单个枚举类型也是System.Enum的子类,并不是System.Object的特例,因此它们注册为而不是课程。

总而言之,不要认为C#的真实内容也适用于.NET。当然,不要认为高级抽象仍然存在 - 从技术上讲,.NET是100%面向对象的,在类层次结构之上有一个“master”System.ValueType。即使System.Object延伸(必须)System.Object。但是 - 值类型实际上不是 System.Object;当你 将它们转移到enum时,你正在创建一个 new 对象,它包装了实际的值类型。

就像一般的值类型一样,.NET Enum是“丑陋的黑客”。就运行时(以及许多内部.NET代码)而言,它们是一个特殊的东西,它们可以为您简化程序员的工作,或者提高性能(以及安全性和安全性,和......)。

最后,正如您所发现的,有些事情必须是不一致的。 ValueType来自struct。根据C#语义, 应该是struct。但是你无法扩展IEnum!然而,在这种情况下,这就是你真正想做的事情。

我怀疑如果将枚举添加到(例如)5.0中的.NET中,它们将以不同的方式实现。也许只是一个{{1}}接口和几个扩展方法。但是在C#1.0中没有扩展方法,对于值类型,它们会施加不必要的性能损失。

答案 1 :(得分:8)

内部IsEnum调用方法

IsSubclassOf(RuntimeType.EnumType)

具有以下实现(请参阅方法的注释):

        // Returns true if this class is a true subclass of c.  Everything 
        // else returns false.  If this class and c are the same class false is
        // returned. 
        //
        [System.Runtime.InteropServices.ComVisible(true)]
        [Pure]
        public virtual bool IsSubclassOf(Type c) 
        {
            Type p = this; 
            if (p == c) 
                return false;
            while (p != null) { 
                if (p == c)
                    return true;
                p = p.BaseType;
            } 
            return false;
        } 

所以它只适用于Enum的后代

IsClass方法更有趣:

public bool IsClass {
            [Pure] 
            get {return ((GetAttributeFlagsImpl() & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Class && !IsValueType);}
        } 
...
 public bool IsValueType {
            [Pure] 
            get {return IsValueTypeImpl();}
        } 
...
 protected virtual bool IsValueTypeImpl() 
        {
            // Note that typeof(Enum) and typeof(ValueType) are not themselves value types. 
            // But there is no point excluding them here because customer derived System.Type
            // (non-runtime type) objects can never be equal to a runtime type, which typeof(XXX) is.
            // Ideally we should throw a NotImplementedException here or just return false because
            // customer implementations of IsSubclassOf should never return true between a non-runtime 
            // type and a runtime type. There is no benefits in making that breaking change though.

            return IsSubclassOf(RuntimeType.ValueType); 
        }

它检查[class]类型的语义,就像你提到的Enum是一个类。然后检查它是否不是值类型(参见上面的代码)