Поделиться через


Реализация явного интерфейса (руководство по программированию на C#)

Если класс реализует два интерфейса, которые содержат член с одной и той же сигнатурой, то реализация этого члена в классе приведет к использованию обоих интерфейсов в качестве их реализации. В следующем примере все вызовы Paint используют один и тот же метод. Этот первый пример определяет типы:

public interface IControl
{
    void Paint();
}
public interface ISurface
{
    void Paint();
}
public class SampleClass : IControl, ISurface
{
    // Both ISurface.Paint and IControl.Paint call this method.
    public void Paint()
    {
        Console.WriteLine("Paint method in SampleClass");
    }
}

Следующий пример вызывает методы:

SampleClass sample = new SampleClass();
IControl control = sample;
ISurface surface = sample;

// The following lines all call the same method.
sample.Paint();
control.Paint();
surface.Paint();

// Output:
// Paint method in SampleClass
// Paint method in SampleClass
// Paint method in SampleClass

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

public class SampleClass : IControl, ISurface
{
    void IControl.Paint()
    {
        System.Console.WriteLine("IControl.Paint");
    }
    void ISurface.Paint()
    {
        System.Console.WriteLine("ISurface.Paint");
    }
}

Член IControl.Paint класса доступен только через IControl интерфейс и ISurface.Paint доступен только через ISurfaceинтерфейс. Обе реализации метода независимы, и ни одна из них не доступна напрямую в классе. Рассмотрим пример.

SampleClass sample = new SampleClass();
IControl control = sample;
ISurface surface = sample;

// The following lines all call the same method.
//sample.Paint(); // Compiler error.
control.Paint();  // Calls IControl.Paint on SampleClass.
surface.Paint();  // Calls ISurface.Paint on SampleClass.

// Output:
// IControl.Paint
// ISurface.Paint

Явная реализация также используется для устранения случаев, когда два интерфейса объявляют разные члены одного и того же имени, например свойство и метод. Для реализации обоих интерфейсов класс должен использовать явную реализацию для свойства Pили метода Pили обоих, чтобы избежать ошибки компилятора. Рассмотрим пример.

interface ILeft
{
    int P { get;}
}
interface IRight
{
    int P();
}

class Middle : ILeft, IRight
{
    public int P() { return 0; }
    int ILeft.P { get { return 0; } }
}

У явной реализации интерфейса нет модификатора доступа, так как он недоступен в качестве члена типа, в который он определен. Вместо этого он доступен только при вызове через экземпляр интерфейса. При указании модификатора доступа для явной реализации интерфейса возникает ошибка компилятора CS0106. Дополнительные сведения см. в разделе interface (Справочник по C#).

Вы можете определить реализацию для членов, объявленных в интерфейсе. Если класс наследует реализацию метода из интерфейса, этот метод доступен только через ссылку типа интерфейса. Унаследованный элемент не отображается как часть общедоступного интерфейса. В следующем примере определяется реализация по умолчанию для метода интерфейса:

public interface IControl
{
    void Paint() => Console.WriteLine("Default Paint method");
}
public class SampleClass : IControl
{
    // Paint() is inherited from IControl.
}

Следующий пример вызывает реализацию по умолчанию:

var sample = new SampleClass();
//sample.Paint();// "Paint" isn't accessible.
var control = sample as IControl;
control.Paint();

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

См. также