方法重载和枚举的奇怪(可能是错误的?)C# 编译器行为
今天我发现了 C# 函数重载的一个非常奇怪的行为。当我有一个具有 2 个重载的方法时,就会出现问题,一个重载接受 Object,另一个接受任何类型的 Enum。当我传递 0 作为参数时,将调用该方法的 Enum 版本。当我使用任何其他整数值时,将调用对象版本。我知道可以通过使用显式转换轻松解决这个问题,但我想知道为什么编译器会这样做。这是一个错误还是只是一些我不知道的奇怪的语言规则?
下面的代码解释了问题(使用运行时 2.0.50727 检查)
感谢您对此的任何帮助, 格热戈日·基茨
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");
}
}
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
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");
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可能不知道存在从常量1 0 到任何枚举的隐式转换:
现在,从 0 到
Bar
的转换比从 0 到object
的转换,这就是使用Foo(Bar)
重载的原因。这样一切就都清楚了吗?
1 实际上,Microsoft C# 编译器中存在一个错误,它允许它为任何零常量,而不仅仅是整数:
这不太可能被修复,因为它可能会破坏现有的工作代码。我相信埃里克·利珀特有两个 博客 帖子,其中有更多详细信息。
C# 规范第 6.1.3 节(C# 4 规范)对此有这样的说法:
这实际上表明该错误不仅仅是允许错误的类型,而是允许转换任何常量 0 值而不仅仅是文字值 0。
编辑:看起来“常量”部分是 在 C# 3 编译器中部分引入< /a>.以前它是一些常量值,现在看起来像是全部。
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
Bar
is more specific than the conversion from 0 toobject
, which is why theFoo(Bar)
overload is used.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:
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.
我知道我在其他地方读过,.NET 系统始终将零视为有效的枚举值,即使实际上不是。我会尝试为此找到一些参考...
好吧,我发现这个,引用以下内容并将其归功于 Eric Gunnerson:
因此,这背后的全部原因似乎只是在检查标志时允许等于零,而不必强制转换为零。
I know I have read somewhere else that the .NET system always treats zero as a valid enumeration value, even if it actually isn't. I will try to find some reference for this...
OK, well I found this, which quotes the following and attributes it to Eric Gunnerson:
So it appears that the whole reason behind this was to simply allow equating to zero when checking flags without having to cast the zero.