Явная реализация интерфейса (Руководство по программированию в 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#).

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

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 по умолчанию либо в качестве открытого метода, либо в качестве реализации интерфейса.

См. также