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

Ars*_*yan 14 .net c# enums

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

Console.WriteLine(typeof(System.Enum).IsEnum) // says it is false
Run Code Online (Sandbox Code Playgroud)

我无法理解逻辑,因此System.Enum不是枚举,但是从它派生的所有东西都是枚举?

当我在msdn中看到它是一个班级时,我第二次震惊

public abstract class Enum : ValueType, 
    IComparable, IFormattable, IConvertible
Run Code Online (Sandbox Code Playgroud)

所以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
Run Code Online (Sandbox Code Playgroud)

Lua*_*aan 9

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

那么,什么是C#结构?这是一个密封的类,扩展了System.ValueType类型.该System.ValueType也是什么决定什么IsClassIsStruct该属性Type类的回报.

那么为什么Type.IsClass返回假?其实很简单.虽然Type.IsClass真的会回归false枚举,但你得到的类型typeof(Enum)实际上并不是System.Type- 它是System.RuntimeType.并且有点不同地System.RuntimeType定义IsValueTypeImpl方法:

return !(this == typeof(ValueType)) 
       && !(this == typeof(Enum)) 
       && this.IsSubclassOf(typeof(ValueType));
Run Code Online (Sandbox Code Playgroud)

所以有一个明确的额外检查 - Enum类型本身,同时从ValueType语义上推导出来,struct实际上被归类为非值类型.

但是派生自的各个枚举类型System.Enum也是子类ValueType,而不是特殊情况System.Enum,所以它们注册为不是类.

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

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

最后,正如您所发现的,有些事情必须是不一致的.Enum来源于ValueType.根据C#语义,它应该是一个struct.但你不能延长一个struct!然而,在这种情况下,这就是你真正想做的事情.

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


And*_*rew 8

内部IsEnum调用以下方法

IsSubclassOf(RuntimeType.EnumType)
Run Code Online (Sandbox Code Playgroud)

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

        // 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;
        } 
Run Code Online (Sandbox Code Playgroud)

所以它只适用于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); 
        }
Run Code Online (Sandbox Code Playgroud)

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