为什么使用 "var" 时,Enum.GetValues() 返回名称?
为什么使用 "var" 时,Enum.GetValues() 返回名称?
有人可以解释一下这个吗?
alt text http://www.deviantsart.com/upload/g4knqc.png
using System; namespace TestEnum2342394834 { class Program { static void Main(string[] args) { //使用"var"关键字 foreach (var value in Enum.GetValues(typeof(ReportStatus))) { Console.WriteLine(value); } //使用"int"关键字 foreach (int value in Enum.GetValues(typeof(ReportStatus))) { Console.WriteLine(value); } } } public enum ReportStatus { Assigned = 1, Analyzed = 2, Written = 3, Reviewed = 4, Finished = 5 } }
Enum.GetValues()返回名称而不是值的原因是因为在代码中使用了object.ToString()
方法。这个方法会返回对象的名称。
解决方法是将object
类型的变量转换为enumType
类型的变量,并使用ToString()
方法获取其值。
这段代码的反汇编结果显示了Enum.GetValues()
方法的实现。该方法首先检查传入的enumType
参数是否为空,如果为空则抛出异常。然后,它检查enumType
是否是RuntimeType
的实例,如果不是则抛出异常。接下来,它检查enumType
是否是枚举类型,如果不是则抛出异常。然后,它获取了enumType
的哈希值,并使用这个哈希值创建了一个数组。接着,它使用ToObject()
方法将哈希值转换为enumType
类型的对象,并将其存储在数组中。最后,它返回这个数组。
根据代码的反汇编结果,我们可以看到Enum.GetValues()
方法返回的是一个包含枚举类型的名称的数组。
,Enum.GetValues()
返回名称而不是值的原因是因为在代码中使用了object.ToString()
方法。要解决这个问题,可以将object
类型的变量转换为enumType
类型的变量,并使用ToString()
方法获取其值。
问题:为什么使用"var"时,Enum.GetValues()
返回的是名称?
原因:在Enum.GetValues()
方法中,返回的数组被声明为Array
类型。该数组包含实际的值作为ReportStatus
类型的值。因此,var
关键字被解析为object
类型,并且value
变量保存了(装箱的)强类型枚举值。当调用Console.WriteLine
时,会解析为接受object
类型参数的重载方法,并在对象上调用ToString()
方法。对于枚举类型,ToString()
方法返回名称。
解决方法:如果想要在循环中输出枚举值而不是名称,可以将value
变量的类型更改为int
。由于编译器会将int
隐式转换为枚举类型,所以value
变量将保存常规的(非装箱的)int
值。这样,Console.WriteLine
调用会解析为接受int
类型参数的重载方法,并将其打印出来。
文章如下:
Enum.GetValues()
方法被声明为返回Array
类型。该方法返回的数组包含实际的枚举值,作为ReportStatus
类型的值。因此,使用var
关键字时,var
会被解析为object
类型,并且value
变量会保存(装箱的)强类型枚举值。当调用Console.WriteLine
方法时,会选择接受object
类型参数的重载方法,并在对象上调用ToString()
方法。对于枚举类型,ToString()
方法返回枚举名称。
如果想要在循环中输出枚举值而不是名称,可以将value
变量的类型更改为int
。编译器会将枚举类型隐式转换为int
类型,因此value
变量将保存常规的(非装箱的)int
值。这样,Console.WriteLine
调用会选择接受int
类型参数的重载方法,并将其打印出来。
如果将int
更改为DateTime
(或其他类型),虽然代码仍然可以编译,但在运行时会抛出InvalidCastException
异常。
因此,Enum.GetValues()
方法返回的IEnumerable
依赖于隐式转换。
注意,如果枚举的基础类型是其他数值类型(例如uint
或short
),第二个循环也会失败。
在第一个循环中,没有进行任何转换操作,而在第二个循环中,只允许继承转换。也就是说,既没有隐式转换,也没有显式定义的转换。
为什么在使用"var"时,Enum.GetValues()返回名称?
根据MSDN文档,Console.WriteLine的重载方法会在其参数上调用ToString方法。当你使用foreach (var value in ...)时,value变量的类型是object(因为Enum.GetValues返回一个不带类型的Array),所以Console.WriteLine调用的是object.ToString方法,而该方法被System.Enum.ToString方法重写。这个重写的方法返回enum的名称。
当你使用foreach (int value in ...)时,你将enum的值转换为int值(而不是object),因此Console.WriteLine调用的是System.Int32.ToString方法。
是的,foreach(ReportStatus会编译并打印名称。
问题出现的原因是,当使用var时,变量的类型被推断为object,而不是具体的枚举类型。因此,调用Console.WriteLine时会调用object.ToString方法,返回枚举的名称。
解决方法是将foreach循环中的变量类型显式指定为具体的枚举类型,例如foreach (ReportStatus value in ...)。这样,Console.WriteLine将调用enum类型的ToString方法,返回具体的枚举值。
总结起来,当使用var时,Enum.GetValues()返回的是不带类型的Array,变量的类型被推断为object,调用Console.WriteLine时返回枚举的名称。要解决这个问题,需要将变量类型显式指定为具体的枚举类型。