Подтвердить что ты не робот

Неопределенное поведение при перегрузке метода

Я борюсь со странным, по крайней мере для меня, методом, перегружающим разрешение .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) вместо заданного типа данных.

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

Обновление

Я должен был указать, что существует другое поведение между С# 2 и С# 3

Do((long)0) => object overload //C# 2
Do((long)0) => enum overload   //C# 3 
4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

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

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

добавив следующее:

test.Execute(+0,0);//перегрузка переполнения: 0

Жак Кольменеро Архитектор предприятия [email protected]

Ответ 3

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

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

Execute((object) 1);

для вывода

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