是.NET枚举类型实际上是可变的值类型? [英] Are .NET enum types actually mutable value types?

查看:148
本文介绍了是.NET枚举类型实际上是可变的值类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来看,与反思,在一个枚举类型的字段,我发现让我吃惊的是保存枚举的特定实例的实际价值的靠山的实例字段是不是私人,因为我想到,但公共。并且它不是只读无论是。 ( IsPublic 真实, IsInitOnly 假的。)

Looking, with reflection, at the fields of an enum type, I noticed to my surprise that the "backing" instance field that holds the actual value of a particular instance of the enum is not private, as I would have thought, but public. And it was not readonly either. (IsPublic true, IsInitOnly false.)

很多人们认为可变值类型在.NET类型系统邪恶的,所以为什么是枚举类型(从例如C#代码创建)的只是

Many people consider "mutable" value types in the .NET type system "evil", so why are the enum types (as created from C# code for example) just that?

现在,事实证明,C#编译器具有某种魔力,否认公网实例场的存在(见下文),但在如PowerShell中,你可以这样做:

Now, as it turns out, the C# compiler has some kind of magic that denies the existence of the public instance field (but see below), but in e.g. PowerShell you can do this:

prompt> $d = [DayOfWeek]::Thursday
prompt> $d
Thursday
prompt> $d.value__ = 6
prompt> $d
Saturday



字段值__ 可写。

现在,要做到这一点在C#中,我不得不使用动态,因为它似乎与正常的编译时成员结合,C#假装在公共实例字段不存在。当然,使用动态,我们将不得不使用枚举值的拳击

Now, to do this in C#, I had to use dynamic because it seems that with the normal compile-time member binding, C# pretends that the public instance field does not exist. Of course to use dynamic, we will have to use boxing of the enum value.

下面是一个C#代码示例:

Here's a C# code example:

// create a single box for all of this example
Enum box = DayOfWeek.Thursday;

// add box to a hash set
var hs = new HashSet<Enum> { box, };

// make a dynamic reference to the same box
dynamic boxDyn = box;

// see and modify the public instance field
Console.WriteLine(boxDyn.value__);  // 4
boxDyn.value__ = 6;
Console.WriteLine(boxDyn.value__);  // 6 now

// write out box
Console.WriteLine(box);  // Saturday, not Thursday

// see if box can be found inside our hash set
Console.WriteLine(hs.Contains(box));  // False

// we know box is in there
Console.WriteLine(object.ReferenceEquals(hs.Single(), box));  // True



我觉得意见不言自明。我们可以变异枚举类型星期几的一个实例,通过公共字段。由于该实例是一个Hashtable和突变导致的哈希码的改变,该实例是在变异后的错误桶,而的HashSet<> 无法运行。

I think the comments speak for themselves. We can mutate an instance of the enum type DayOfWeek (could be any enum type from a BCL assembly or from a "home-made" assembly) through a public field. Since the instance was in a hashtable and the mutation lead to a change of hash code, the instance is in the wrong "bucket" after the mutation, and the HashSet<> cannot function.

为什么.NET的设计者选择将枚举类型的实例字段公共

Why did the designers of .NET choose to make the instance field of enum types public?

推荐答案

让我尽量让这个相当混乱的问题意识为读者谁不熟悉如何枚举在后台生成。 C#代码:

Let me try to make sense of this rather confusing question for readers who are unfamiliar with how enums are generated behind the scenes. The C# code:

enum E { A, B }

成为IL

.class private auto ansi sealed E extends [mscorlib]System.Enum
{
  .field public specialname rtspecialname int32 value__
  .field public static literal valuetype E A = int32(0x00000000)
  .field public static literal valuetype E B = int32(0x00000001)
} 

或者,再次改写,在C#中,枚举相当于以下伪C#:

Or, to rewrite that in C# again, the enum is equivalent to the following pseudo-C#:

struct E : System.Enum
{
    public int value__;
    public const E A = 0;
    public const E B = 1;
}



现在的问题是:为什么是神奇的领域 value__ 公开?

我不在身边的这个设计决定的,所以我必须做出一个受过教育的猜测。我的猜测是:如何如果字段是不公开的,你初始化结构的实例?

I wasn't around for this design decision, so I'd have to make an educated guess. My educated guess would be: how do you initialize an instance of the struct if the field is not public?

您做一个构造函数,你就必须打电话,那是给工作的抖动,这是什么工作的性能代价买吗?如果答案是它给我买了运行时防止自己从做一些愚蠢和危险的,我不应该摆在首位做,不得不非常努力做到在所有,那么我向你,这是不是一个引人注目的成本效益比。

You make a constructor, which you then have to call, and that is giving work to the jitter, and what does the performance cost of that work buy you? If the answer is "it buys me the runtime preventing myself from doing something foolish and dangerous that I shouldn't be doing in the first place and had to work really hard to do at all" then I submit to you that this is not a compelling cost-to-benefit ratio.

由于实例是在一个Hashtable和突变导致的哈希码的改变,该实例在变异后的错误桶,而HashSet中不能正常工作。

Since the instance was in a hashtable and the mutation lead to a change of hash code, the instance is in the wrong "bucket" after the mutation, and the HashSet cannot function.

这是几英里过去的,如果它伤害时,你这样做,然后点击停止这样做行。

That's several miles past the "if it hurts when you do that then stop doing that" line.

这篇关于是.NET枚举类型实际上是可变的值类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆