奇怪(可能是错误的)C#编译器行为与方法重载和枚举 [英] Strange (possibly wrong?) C# compiler behavior with method overloading and enums
问题描述
下面的代码解释了问题(使用运行时2.0.50727检查)
感谢任何帮助,
Grzegorz Kyc
类程序
{
enum Bar
{
Value1,
Value2,
Value3
}
static void Main string [] args)
{
Foo(0);
Foo(1);
Console.ReadLine();
}
static void Foo(object a)
{
Console.WriteLine(object);
}
static void Foo(Bar a)
{
Console.WriteLine(enum);
}
}
可能你不知道有一个常量 1 0到任何枚举的隐式转换:
Bar x = 0; //隐式转换
现在,从0到 Bar
比从0到对象
的转换更具体,这就是为什么 Foo(Bar)
是否清除所有内容?
1 Microsoft C#编译器中实际上有一个错误,它允许它为任何零常量,而不仅仅是一个整数:
const decimal DecimalZero = 0.0m;
...
Bar x = DecimalZero;
这不可能修复,因为它可能会破坏现有的工作代码。我相信Eric Lippert有两个博客 C#规范部分6.1.3(C#4规范)具有这就是说: 隐式枚举转换 这实际上表明该错误不仅仅是允许错误的类型,而是允许任何常量0值被转换,而不仅仅是字面值0。 编辑:看起来像常数部分是部分介绍在C#3编译器中。以前,这是一些常数值,现在看起来像是全部。 today I discovered a very strange behavior with C# function overloading. The problem occurs when I have a method with 2 overloads, one accepting Object and the other accepting Enum of any type. When I pass 0 as parameter, the Enum version of the method is called. When I use any other integer value, the Object version is called. I know this can be easilly fixed by using explicit casting, but I want to know why the compiler behaves that way. Is this a bug or just some strange language rule I don't know about? The code below explains the problem (checked with runtime 2.0.50727) Thanks for any help on this,
Grzegorz Kyc
It may be that you're not aware that there's an implicit conversion from a constant1 of 0 to any enum: Now, the conversion from 0 to Does that clear everything up? 1 There's actually a bug in the Microsoft C# compiler which lets it be any zero constant, not just an integer: It's unlikely that this will ever be fixed, as it could break existing working code. I believe Eric Lippert has a two blog posts which go into much more detail. The C# specification section 6.1.3 (C# 4 spec) has this to say about it: An implicit enumeration conversion
permits the decimal-integer-literal 0
to be converted to any enum-type and
to any nullable-type whose underlying
type is an enum-type. In the latter
case the conversion is evaluated by
converting to the underlying enum-type
and wrapping the result (§4.1.10). That actually suggests that the bug isn't just in allowing the wrong type, but allowing any constant 0 value to be converted rather than only the literal value 0. EDIT: It looks like the "constant" part was partially introduced in the C# 3 compiler. Previously it was some constant values, now it looks like it's all of them. 这篇关于奇怪(可能是错误的)C#编译器行为与方法重载和枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
允许十进制整数字符 0
要转换为任何枚举类型,
转换为其底层
类型为枚举类型的任何可空类型。在后者
的情况下,转换由
转换为底层的枚举类型
并包装结果(§4.1.10)。
class Program
{
enum Bar
{
Value1,
Value2,
Value3
}
static void Main(string[] args)
{
Foo(0);
Foo(1);
Console.ReadLine();
}
static void Foo(object a)
{
Console.WriteLine("object");
}
static void Foo(Bar a)
{
Console.WriteLine("enum");
}
}
Bar x = 0; // Implicit conversion
Bar
is more specific than the conversion from 0 to object
, which is why the Foo(Bar)
overload is used.
const decimal DecimalZero = 0.0m;
...
Bar x = DecimalZero;