Меня смущает следующий сценарий на С#, касающийся разрешения реализации интерфейса. Следующий код компилируется без ошибок:
interface IA
{
void Method();
}
class CustomAttribute : Attribute { }
interface IB : IA
{
[Custom]
new void Method();
}
class BaseA : IA
{
public void Method() => Console.WriteLine("Implementation in base");
}
class B: BaseA, IB
{
new public void Method() => Console.WriteLine("Implementation in B");
}
class C : BaseA, IB
{
}
Интерфейс IA находится в библиотеке классов, к которой у нас нет доступа, в IB мы добавляем к методу собственный атрибут. Я ожидал, что Class C потребует другой реализации для Method, отличной от той, что в BaseA.
Мой вопрос: почему в class C реализация new Method для IB выбирается из BaseA, в то время как она отмечена new в IB?
Где в спецификации C# указано, как разрешить реализацию в таком случае?
Есть ли у этого процесса разрешения название?
@Дай Да, это правда. Спасибо за упоминание. Он по-прежнему компилируется без «нового» с предупреждениями.
измените class C : BaseA, IB на class C : B, если вам нужна реализация с IB.
@Luuk Нет, мне просто интересно, почему компилируется класс C.





Есть ли у этого процесса разрешения название?
Во время сопоставления интерфейса компилятор всегда проверяет, есть ли в базовых классах реализация этого члена интерфейса.
(Выделено мной)
Отображение интерфейса для класса или структуры C находит реализацию для каждого члена каждого интерфейса, указанного в списке базовых классов
C. Реализация конкретного члена интерфейсаI.M, гдеI— это интерфейс, в котором объявлен членM, определяется путем проверки каждого класса или структурыS, начиная сCи повторяя для каждого последующего базового классаC, пока не будет найдено совпадение. ...
Если
Sсодержит объявление явной реализации члена интерфейса, соответствующееIиM, то этот член является реализацияI.M.В противном случае, если
Sсодержит объявление нестатического открытого члена, соответствующегоM, то этот член является реализациейI.M. [...]
Для обычного публичного метода, такого как BaseA.Method, нет ничего, что мешало бы его сопоставлению как с IA.Method, так и с IB.Method.
Однако если бы BaseA.Method был явной реализацией интерфейса:
class BaseA : IA
{
void IA.Method() => Console.WriteLine("Implementation in base");
}
Тогда его можно будет сопоставить только с IA.Method, и class C: BaseA, IB {} выдаст ошибку компилятора.
Кстати, вы можете опустить оба ключевых слова
new, и он все равно будет создаваться и работать (просто игнорируйте предупреждение о непреднамеренном сокрытии).