Метод перегрузки разрешает неожиданное поведение - PullRequest
17 голосов
/ 11 января 2010

Я борюсь со странным, по крайней мере для меня, методом перегрузки разрешения .net. Я написал небольшой пример, чтобы воспроизвести проблему:

class Program
{
    static void Main(string[] args)
    {
        var test = new OverloadTest();
        test.Execute(0);
        test.Execute(1);

        Console.ReadLine();
    }
}

public class OverloadTest
{
    public void Execute(object value)
    {
        Console.WriteLine("object overload: {0}", value);
    }

    public void Execute(MyEnum value)
    {
        Console.WriteLine("enum overload: {0}", value);
    }
}

public enum MyEnum
{ 
    First = 1, Second = 2, Third = 3
}

Напечатает:

enum overload: 0
object overload: 1

В основном вызванная перегрузка отличается в зависимости от значения (0, 1) вместо заданного типа данных.

Может кто-нибудь объяснить?

Обновление

Я должен был указать, что между C # 2 и C # 3

существует другое поведение *
Do((long)0) => object overload //C# 2
Do((long)0) => enum overload   //C# 3 

Ответы [ 3 ]

16 голосов
/ 11 января 2010

Да - константа 0 неявно может быть преобразована в любой тип перечисления. Константа 1 только явно может быть преобразована в тип enum. Оба неявно преобразуются в object (через бокс), но преобразование в перечисление предпочтительнее, если оно доступно.

Обратите внимание, что не имеет никакого отношения к каким значениям определяет перечисление. Преобразование для любого ненулевого значения является явным, соответствует ли оно значению в перечислении или нет. Это просто особый случай для значения 0, что упрощает некоторый другой код (особенно при работе с флагами). Боюсь, у меня нет спецификации, чтобы найти ссылку.

Бонус странности: из-за ошибки в компиляторе MS (никогда не исправить - это нарушит обратную совместимость) на самом деле это различные нулевые константы , а не просто целое число. Так что Execute(0d) и Execute(0m) будут также преобразовывать двойное и десятичное в перечисление. Он не работает для каждой нулевой константы - это зависит от точной природы исходного кода. Это все очень странно - перейдите по ссылке, где Эрик Липперт раскрывает все ...

0 голосов
/ 14 декабря 2010

Я согласен с ответом Джона Скита - см. Его пост (выше) 11 января в 17:32. Чтобы расширить, пожалуйста, обратитесь к спецификации языка C # - страница: 110

6.1.3 Неявные перечисления Неявное преобразование перечисления позволяет преобразовать десятичный целочисленный литерал 0 в любой тип перечисления и в любой тип, допускающий значение null, базовый тип которого является типом перечисления В последнем случае преобразование оценивается путем преобразования в базовый тип enum и переноса результата (§4.1.10).

Все еще существует проблема:

добавив оператор:

test.Execute (-0.0); // перегрузка объекта: 0

при добавлении следующего:

test.Execute (+0,0); // enum overload: 0

Жак Кольменеро Enterprise Architect colmeneroj@videotron.ca

0 голосов
/ 11 января 2010

Enum просто отображается в int (по умолчанию). 0 не соответствует вашему Enum, поэтому используется перегрузка, которая принимает объект 1 соответствует вашему enum, поэтому используется перегрузка Enum.

Вы можете сделать это:

Execute((object) 1);

для вывода

перегрузка объекта: 1

...