gpt4 book ai didi

c# - Enum.GetValues() 的内部工作

转载 作者:行者123 更新时间:2023-11-30 13:22:30 25 4
gpt4 key购买 nike

在阅读某人的源代码时,我遇到了一个 C# 片段,其行为让我感到困惑。在我开始提问之前,这里有一个改编的例子:

枚举:

private enum Seasons
{
Spring,
Summer,
Autumn,
Winter
}

用法:

foreach(Seasons value in Enum.GetValues(typeof(Seasons)))
{
Console.WriteLine(String.Format("{0} {1}", value, (int) value));
}

输出看起来像这样:

Spring 0
Summer 1
Autumn 2
Winter 3

我的问题:

这在 C# 中是如何工作的?返回值来自:

Enum.GetValues(typeof(Seasons))

是一个 int 数组,其中填充了 0-3 的值。当它被转换为 Seasons 枚举时,我首先预计它会失败。

我认为由于 enum 是一个引用类型,在 String.Format() 参数“值”上,将调用 ToString() 方法,它将返回它的名字。但是当转换为 int 时,它将使用该“命名”值上的属性并返回 int 值。

如果有人能告诉我这是如何在幕后运作的,我会很高兴。我查看了文档,但还无法解决。

谢谢...


谢谢大家的回答!

但是......如果有人能多谈谈 C# 内部结构,我将不胜感激。在 Java 中,枚举将是一个真正的引用类型,在内存中,它将被视为指向另一个存储整数的内存空间的引用。像这样非常非常简单。

---------               -----------------
| | Reference |int Spring |
|Seasons|-------------> |int Summer |
| | |int Autumn |
--------- |int Winter |
-----------------

在我看来,在 C# 中,编译器将其转换为类似 public const 的东西(在我的例子中是 int)。请不要扔石头...

最佳答案

Seasons 类型的变量可以被赋予基础类型范围内的任何值(整数在这种情况下)。值甚至不限于枚举的命名常量。因此,通过将整数值 5 转换为 Seasons 类型来实例化 Seasons 值是完全合法的:

Seasons season = (Seasons)5;

更新:首先要注意的是 - System.Enum 是一种值类型(它继承自 ValueType),如 DateTime、Int32 或 Boolean。如果您查看为 Seasons 枚举定义生成的 IL,您会看到

.class public auto ansi sealed Seasons
extends [mscorlib]System.Enum
{
.field public static literal valuetype Foo.Seasons Autumn = int32(2)
.field public static literal valuetype Foo.Seasons Spring = int32(0)
.field public static literal valuetype Foo.Seasons Summer = int32(1)
.field public specialname rtspecialname int32 value__
.field public static literal valuetype Foo.Seasons Winter = int32(3)
}

所以,这是一组公共(public)静态字段,它们被标记为文字 - 这使得编译器将枚举值直接嵌入到代码中。例如。以下代码

Seasons season = Seasons.Autumn;
Console.WriteLine(season);

编译后将只有枚举 Autumn 成员的值:

.locals init (
[0] valuetype Foo.Seasons seasons) // it's value type!
L_0000: nop
L_0001: ldc.i4.2 // here simple integer value 2 is loaded
L_0002: stloc.0
L_0003: ldloc.0
L_0004: box Foo.Seasons
L_0009: call void [mscorlib]System.Console::WriteLine(object)

因此,实际上您已将基础类型的值分配给枚举类型的变量。名称或值没有特殊属性。只是(任何)整数常量。

现在关于获取枚举的所有值 - 当您调用 Enum.GetValues 时,它会返回来自私有(private) Hashtable fieldInfoHash 的值,您可以在枚举 类。 Hashtable 缓存枚举的名称和值。因此,当您第一次获取枚举值时,HashEntry 具有枚举类型的值(ulong 数组)和名称(string 数组)是创建。实际上,如果您调用其他 Enum 方法,如 GetNamesIdDefined,将使用此缓存。

在为枚举类型缓存条目后,返回它的值数组。但是用一招。这不是 ulong 值的简单数组。每个值都作为枚举类型用 Enum.ToObject 调用装箱(您可以在 System.RuntimeType 中找到实现):

ulong[] values = Enum.InternalGetValues(this);
Array array = Array.UnsafeCreateInstance(this, values.Length);
for (int i = 0; i < values.Length; i++)
{
object obj2 = Enum.ToObject(this, values[i]);
array.SetValue(obj2, i);
}
return array;

这就是为什么每个值对象都是 Seasons 类型而不是 ulong 类型的原因。

关于c# - Enum.GetValues() 的内部工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21183119/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com