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