Почему я не могу вызвать методы в классе, который явно реализует интерфейс? - PullRequest
35 голосов
/ 26 марта 2010

Вот история. Я создал интерфейс, IVehicle. Я явно реализовал интерфейс в своем классе, Vehicle.cs.

Вот мой интерфейс:

Interface IVehicle
{
        int getWheel();
}

вот мой класс:

class Vehicle: IVehicle
{

     public int IVehicle.getWheel()
     {
         return wheel;
     }

     public void printWheel()
     {
         Console.WriteLine(getWheel());
     }
}

Обратите внимание, что getWheel() явно реализован. Теперь, когда я пытаюсь вызвать этот метод в моем классе Vehicle, я получаю сообщение об ошибке, указывающее, что getWheel() не существует в текущем контексте. Может ли кто-нибудь помочь мне понять, что я делаю неправильно?

Ответы [ 3 ]

39 голосов
/ 26 марта 2010

Когда вы явно реализуете интерфейс, вы сначала должны привести объект к интерфейсу, затем вы можете вызвать метод. Другими словами, метод доступен только тогда, когда метод вызывается для объекта как тип интерфейса, а не как конкретный тип.

class Vehicle: IVehicle {

     public int IVehicle.getWheel()
     {
         return wheel;
     }

     public void printWheel()
     {
         Console.WriteLine( ((IVehicle)this).getWheel() );
     }
}

См. Эту ссылку на MSDN для получения дополнительной информации. Вот соответствующий фрагмент:

Невозможно получить доступ к реализации явного члена интерфейса через его полностью определенное имя в вызове метода, доступе к свойству или доступу индексатора. Явная реализация члена интерфейса может быть доступна только через экземпляр интерфейса, и в этом случае на него ссылается просто его имя члена.

Для чего это стоит - это, вероятно, не очень хорошее использование явной реализации интерфейса. Как правило, вы хотите использовать явную реализацию, когда у вас есть класс, который имеет полный интерфейс для типичных операций, но также реализует интерфейс, который может заменить некоторые из этих операций. Каноническим примером является класс File, который реализует IDisposable. Он будет иметь метод Close(), но потребуется для реализации Dispose(). При обработке File вы должны использовать Open/Close. Однако при открытии в операторе using он будет обрабатываться как IDisposable и вызывать Dispose. В этом случае Dispose просто звонит Close. Вам не обязательно показывать Dispose как часть реализации File, поскольку такое же поведение доступно с Close.

12 голосов
/ 26 марта 2010

Согласно MSDN :

Возможно реализовать член интерфейса явно - создание член класса, который называется только через интерфейс , а конкретно к этому интерфейсу.

А в спецификациях C # :

Невозможно получить доступ к явный член интерфейса реализация через его полностью квалифицированное имя в вызове метода, доступ к свойству или доступ к индексатору. явный член интерфейса реализация может быть доступна только через экземпляр интерфейса и в этом случае ссылается просто его имя участника.

Для доступа к этому члену вы можете сначала привести класс к интерфейсу, а затем получить к нему доступ.

3 голосов
/ 24 апреля 2015

Чтобы избежать скучных бросков в вашем классе, вы можете создать указатель в качестве типа интерфейса

public class Foo : IBar
{
    readonly IBar bar;
    public Foo()
    {
       bar = this;
    }
}

А затем вызывать участников, используя bar.

...