为什么我不能通过一次隐式转换来打开一个类到枚举
我想知道为什么到枚举值的单个隐式转换的工作方式与转换到系统类型时的工作方式不同。我看不出任何技术原因,但也许比我聪明的人可以为我提供一些启发。
以下代码无法使用“需要整数类型的值”
和“无法将类型'Test.En'隐式转换为'Test.Foo”
进行编译。
void test1 (){
Foo f = new Foo();
switch (f) // Comment this line to compile
//switch ((En)f) // Uncomment this line to compile
{
case En.One:
break;
}
}
//////////////////////////////////////////////////////////////////
public enum En
{
One,
Two,
Three,
}
public class Foo
{
En _myEn;
public static implicit operator En(Foo f)
{
return f._myEn;
}
}
编辑来自规范:
switch 语句的控制类型是由 switch 表达式建立的。如果 switch 表达式的类型是 sbyte、byte、short、ushort、int、uint、long、ulong、char、string 或 enum-type,那么这就是 switch 的控制类型陈述。否则,必须存在从 switch 表达式的类型到以下可能的控制类型之一的用户定义的隐式转换(第 6.4 节):sbyte、byte、short、ushort、int、uint、long、ulong、字符,字符串。如果不存在此类隐式转换,或者存在多个此类隐式转换,则会发生编译时错误。
为了澄清这个问题,为什么枚举类型不包含在允许的用户定义的隐式转换列表中?
I am wondering why it is that a single implicit conversion to an enum value doesn't work the same way it would if the conversion were to a system type. I can't see any technical reason however maybe someone smarter than I can shed some light for me.
The followoing fails to compile with, "A value of an integral type expected"
and "Cannot implicitly convert type 'Test.En' to 'Test.Foo"
.
void test1 (){
Foo f = new Foo();
switch (f) // Comment this line to compile
//switch ((En)f) // Uncomment this line to compile
{
case En.One:
break;
}
}
//////////////////////////////////////////////////////////////////
public enum En
{
One,
Two,
Three,
}
public class Foo
{
En _myEn;
public static implicit operator En(Foo f)
{
return f._myEn;
}
}
edit from the spec:
The governing type of a switch statement is established by the switch expression. If the type of the switch expression is sbyte, byte, short, ushort, int, uint, long, ulong, char, string, or an enum-type, then that is the governing type of the switch statement. Otherwise, exactly one user-defined implicit conversion (§6.4) must exist from the type of the switch expression to one of the following possible governing types: sbyte, byte, short, ushort, int, uint, long, ulong, char, string. If no such implicit conversion exists, or if more than one such implicit conversion exists, a compile-time error occurs.
To Clarify the question, why is an enum-type not included with the list of allowed user-defined implicit conversions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
语言设计说明存档没有提供此决定的理由。这是不幸的,因为决定改变了。正如您所看到的,该设计随着时间的推移而演变:
1999 年 5 月 26 日的注释:
1999 年 6 月 7 日:
1999 年 12 月 20 日:
这里我们第一次出现了相关规则。枚举似乎已经消失了。为什么不使用用户定义的隐式转换为枚举?这只是一个疏忽吗?设计师没有记录他们的想法。
请注意,第一句话不是我们实现的。我不清楚为什么实施者的做法与设计委员会的建议相反。 笔记中再次出现了这一点:
几年后,2003 年 8 月 13 日的
我觉得这很愚蠢;当我们制作 C# 3.0 规范的带注释的印刷版时,我将 bool (和 bool?) 添加到合法管理类型列表中。
简而言之:整个事情有点混乱。我不知道为什么枚举先输入,然后输出,然后半进半出。这可能仍然是未知之谜之一。
The language design notes archive does not provide a justification for this decision. This is unfortunate, since the decision was changed. As you can see, the design evolved over time:
Notes from May 26th, 1999:
June 7th, 1999:
December 20th, 1999:
Here we have the first occurence of the rule in question. Enums seem to have disappeared. And why not use user-defined implicit conversions to enum? Was this simply an oversight? The designers did not record their thoughts.
Note that the first sentence is NOT what we implemented. It is unclear to me why the implementors did the opposite of what the design committee recommended. This comes up again in the notes several years later:
August 13, 2003:
I decided that this was silly; when we produced the annotated print edition of the C# 3.0 specification, I added bool (and bool?) to the list of legal governing types.
In short: the whole thing is a bit of a mess. I have no idea why enums were in, then out, then half-in-half-out. This might have to remain one of the Mysteries of the Unknown.
因为出于切换的目的,枚举被视为整数,并且正如我之前所问的,编译器不会执行多次隐式转换来获取可用类型,它无法弄清楚如何打开 foo。
关于为什么不能像这样使用枚举的唯一理论是,枚举本身不是整数类型,因此编译器必须执行多个隐式转换才能从 foo 获取整数基元。
我编译然后反映了你的代码,结果如下:
所以显然在幕后它确实做了隐式转换。 :S
Because enums are treated as integers for the purpose of switching, and as i've asked before, the compiler doesn't do multiple implicit conversions to get to a usable type, it can't figure out how to switch on foo.
My only theory as to why enums can't be used like that is that enums are not an integer type in and of themselves, and thus the compiler would have to do multiple implicit conversions to get to an integer primitive from foo.
I compiled then reflected your code and here's the results:
So apparently under the covers it does do an implicit conversion. :S
编辑:由于
switch
需要整数值,因此编写switch(f)
会使编译器寻找从Foo
实例到整数类型的转换,它不存在。EDIT: Since
switch
expects an integral value, writingswitch(f)
makes the compiler look for conversion from an instance ofFoo
to an integral type, which doesn't exist.如果您的类包含两个枚举并且两者都有隐式转换运算符怎么办?或者更好的是,如果您有 enum 和 int 的隐式转换运算符怎么办?当您编写 switch 语句时,编译器会“自动”为您选择哪种转换?
您必须明确指定 switch 语句中使用的对象类型。隐式运算符只是告诉编译器/运行时“如果您有 Foo 并且需要 En,则此代码会执行此操作”。它不会更改对象的实际基础类型。
What if your class contained two enums and had implicit conversion operators for both? Or better yet, what if you had implicit conversion operators for an enum and int? Which conversion would the compiler "automatically" pick for you when you write a switch statement?
You have to explicitly specify what type of object is being used inside the switch statement. Implicit operators just tell the compiler/runtime "if you have a Foo and need an En, this code does that". It does not change the actual underlying type of the object.
查看第二条错误消息。编译器尝试对枚举进行类型强制以匹配 switch 语句中的类型。
作为一个兴趣点,它的表现如何?
Take a look at that second error message. The compiler is trying to type-coerce the enum to match the type of what is in the switch statement.
As a point of interest, how does this fare?