奇怪的(可能是错误的?)带有方法重载和枚举的 C# 编译器行为 [英] Strange (possibly wrong?) C# compiler behavior with method overloading and enums

查看:19
本文介绍了奇怪的(可能是错误的?)带有方法重载和枚举的 C# 编译器行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天我发现了 C# 函数重载的一个非常奇怪的行为.当我有一个具有 2 个重载的方法时,就会出现问题,一个接受 Object,另一个接受任何类型的 Enum.当我将 0 作为参数传递时,将调用该方法的 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?

下面的代码解释了问题(用运行时 2.0.50727 检查)

The code below explains the problem (checked with runtime 2.0.50727)

感谢您对此的任何帮助,Grzegorz Kyc

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");
    }
}

推荐答案

您可能不知道存在从常量1 0 到任何枚举的隐式转换:

It may be that you're not aware that there's an implicit conversion from a constant1 of 0 to any enum:

Bar x = 0; // Implicit conversion

现在,从 0 到 Bar 的转换比从 0 到 object 的转换更具体,这就是为什么 Foo(Bar)> 使用了重载.

Now, the conversion from 0 to Bar is more specific than the conversion from 0 to object, which is why the Foo(Bar) overload is used.

这能解决所有问题吗?

1 Microsoft C# 编译器中实际上存在一个错误,它允许它是任何 零常量,而不仅仅是一个整数:

1 There's actually a bug in the Microsoft C# compiler which lets it be any zero constant, not just an integer:

const decimal DecimalZero = 0.0m;

...
Bar x = DecimalZero;

这不太可能被修复,因为它可能会破坏现有的工作代码.我相信 Eric Lippert 有两个 博客 帖子 更详细.

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.

C# 规范第 6.1.3 节(C# 4 规范)对此进行了说明:

The C# specification section 6.1.3 (C# 4 spec) has this to say about it:

隐式枚举转换允许 decimal-integer-literal 0转换为任何枚举类型和任何可空类型type 是一个枚举类型.在后者如果转换由转换为底层enum-type并包装结果(第 4.1.10 节).

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).

这实际上表明该错误不仅在于允许错误的类型,还在于允许转换任何常量 0 值,而不仅仅是字面值 0.

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.

它看起来像常数"部分是 在 C# 3 编译器中部分引入.以前它是一些常量值,现在看起来它是全部.

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屋!

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