我们知道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
答案 0 :(得分:9)
IL不知道结构。 IL只有课程。
那么,什么是C#结构?它是一个密封的类,扩展了System.ValueType
类型。 System.ValueType
也决定IsClass
类的IsStruct
和Type
属性返回的内容。
那么为什么Type.IsClass
会返回false?其实很简单。虽然Type.IsClass
实际上会为枚举返回false
,但您获得的类型为typeof(Enum)
。 System.Type
实际上不是System.RuntimeType
- 它是System.RuntimeType
。并且IsValueTypeImpl
对return !(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是一个类。然后检查它是否不是值类型(参见上面的代码)