Индексатор с параметром enum -- баг в CLR?
От: diamondio  
Дата: 08.10.07 09:26
Оценка:
Добрый день!

Столкнулись со следующей ситуацией:

Есть базовый класс, содержащий индексатор с параметром int:
    public class MyBase
    {
        public string this[int en] { get { return "Int"; } }
    }


и наследник, содержащий индексатор с параметром enum:
    public class MyClass : MyBase
    {
        public string this[MyEnum en] { get { return "Enum"; } }
    }


При попытке использовать индексаторы _всегда_ вызывается this[MyEnum en]:
            MyClass c = new MyClass();
            Console.WriteLine("Enum: " + c[MyEnum.A]);
            Console.WriteLine("Int: " + c[0]);


Enum: Enum
Int: Enum


Собственно вопрос -- почему такое происходит?

Если добавить в MyClass определение нового индексатора код начинает вести себя нормально:
public string new this[int i] { { get { return base[i];} } }


Поведение устойчиво воспроизводится на .NET 1.1 и 2.0.
Re: Индексатор с параметром enum -- баг в CLR?
От: _FRED_ Черногория
Дата: 08.10.07 09:34
Оценка:
Здравствуйте, diamondio, Вы писали:

D>Собственно вопрос -- почему такое происходит?


Потому что сущёствует неявное преобразование из 0 в enum. Поэтому индексатор в наследнике оказывается предподчтительней.
Вот так будет работать, как ожидаается:
int i = 0;
Console.WriteLine(c[i]);
Console.WriteLine(c[1]);
Help will always be given at Hogwarts to those who ask for it.
Re: Индексатор с параметром enum -- баг в CLR?
От: nikov США http://www.linkedin.com/in/nikov
Дата: 08.10.07 09:35
Оценка: 1 (1)
Здравствуйте, diamondio, Вы писали:

D>Собственно вопрос -- почему такое происходит?


Это не баг. Литерал 0 может быть неявно преобразован в любой enum. А если в производном типе есть function member (в частности, индексатор) с подходящей сигнатурой, то члены базовых классов исключаются из рассмотрения. Это обсуждалось на форуме несколько раз, например здесь
Автор: nikov
Дата: 23.03.07
.

И кстати, CLR здесь не при чем — это особенность компилятора C#.
Re[2]: Индексатор с параметром enum -- баг в CLR?
От: _FRED_ Черногория
Дата: 08.10.07 09:36
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Вот так будет работать, как ожидаается:


Или даже так
Console.WriteLine(c[(int)0]);
Help will always be given at Hogwarts to those who ask for it.
Re[3]: Индексатор с параметром enum -- баг в CLR?
От: diamondio  
Дата: 08.10.07 09:54
Оценка:
Здравствуйте, _FRED_, Вы писали:


_FR>
Console.WriteLine(c[(int)0]);


Так не работает. В остальном -- вы правы.

Показалось сначала, что такое поведение не только с 0, это и ввело в замешательство.
Re[4]: Индексатор с параметром enum -- баг в CLR?
От: _FRED_ Черногория
Дата: 08.10.07 10:03
Оценка:
Здравствуйте, diamondio, Вы писали:

_FR>>
Console.WriteLine(c[(int)0]);


D>Так не работает. В остальном -- вы правы.


Что именно "не работает"? У меня вызывается индексатор базового класса (с параметром int).

D>Показалось сначала, что такое поведение не только с 0, это и ввело в замешательство.


На самом деле в примере просто "режет глаза" использование именно нуля: так и кажется, что в нуле-от и лопата
Help will always be given at Hogwarts to those who ask for it.
Re[5]: Индексатор с параметром enum -- баг в CLR?
От: diamondio  
Дата: 08.10.07 10:12
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>>>
Console.WriteLine(c[(int)0]);


_FR>Что именно "не работает"? У меня вызывается индексатор базового класса (с параметром int).


А у меня -- вызывается enum-нутый.

        Console.WriteLine("Enum: " + c[MyEnum.A]);
           Console.WriteLine("Int: " + c[(int)0]);


Правда, каст к инту в IDE выделен серым -- решарпер постарался -- но вряд ли он его удаляет из кода при компиляции, верно?
Re[6]: Индексатор с параметром enum -- баг в CLR?
От: _FRED_ Черногория
Дата: 08.10.07 10:15
Оценка:
Здравствуйте, diamondio, Вы писали:

D>А у меня -- вызывается enum-нутый.

D>Console.WriteLine("Int: " + c[(int)0]);

D>Правда, каст к инту в IDE выделен серым -- решарпер постарался -- но вряд ли он его удаляет из кода при компиляции, верно?

А можешь объяснить, почему вызывается "enum-нутый"?
Help will always be given at Hogwarts to those who ask for it.
Re: Индексатор с параметром enum -- баг в CLR?
От: nikov США http://www.linkedin.com/in/nikov
Дата: 08.10.07 10:31
Оценка: 81 (2)
Здравствуйте, diamondio, Вы писали:

D>При попытке использовать индексаторы _всегда_ вызывается this[MyEnum en]:


Объяснение, почему в C# было принято решение поступать именно так, можно почитать в этой заметке.
Re[7]: Индексатор с параметром enum -- баг в CLR?
От: diamondio  
Дата: 08.10.07 10:41
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, diamondio, Вы писали:


D>>А у меня -- вызывается enum-нутый.

_FR>
D>>Console.WriteLine("Int: " + c[(int)0]);
_FR>

D>>Правда, каст к инту в IDE выделен серым -- решарпер постарался -- но вряд ли он его удаляет из кода при компиляции, верно?

_FR>А можешь объяснить, почему вызывается "enum-нутый"?


Видимо, компилятор игнорирует type cast как redundant. Хотя это смущает. Я бы ожидал, что вызовется как раз int-овый метод.
Re[8]: Индексатор с параметром enum -- баг в CLR?
От: _FRED_ Черногория
Дата: 08.10.07 11:36
Оценка:
Здравствуйте, diamondio, Вы писали:

D>Видимо, компилятор игнорирует type cast как redundant. Хотя это смущает. Я бы ожидал, что вызовется как раз int-овый метод.


Да, это у меня ошибочка вышла
Help will always be given at Hogwarts to those who ask for it.
Re[9]: Индексатор с параметром enum -- баг в CLR?
От: nikov США http://www.linkedin.com/in/nikov
Дата: 08.10.07 11:48
Оценка: 6 (1)
Здравствуйте, _FRED_, Вы писали:

D>>Видимо, компилятор игнорирует type cast как redundant. Хотя это смущает. Я бы ожидал, что вызовется как раз int-овый метод.


_FR>Да, это у меня ошибочка вышла


Это известное отклонение компилятора от стандарта. Хотя там написано:

An implicit enumeration conversion permits the decimal-integer-literal 0 to be converted to any enum-type.


, фактически компилятор позволяет неявное преобразование от любого constant expression, значение которого равно 0, 0.0, 0.0F или 0.0M. Похоже, это чинить пока не собираются.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.