Полное руководство по языку программирования С# 14 и платформе .NET 10 / Интерфейсы

Явная реализация интерфейсов

Начальный ⏱ 4 мин чтения 👁 2 🕓 обновлено 11.08.2026

Кроме неявного применения интерфейсов, которое было рассмотрено в прошлой статье, существует также явная реализация интерфейса. При явной реализации указывается название метода или свойства вместе с названием интерфейса. При этом при реализации мы не можем использовать какие-либо модификаторы:


interface IAction
{
	void Move();
}
class BaseAction : IAction
{
	void IAction.Move() => Console.WriteLine("Move in Base Class");
}

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


BaseAction baseAction1 = new BaseAction();

// baseAction1.Move();  // ! Ошибка - в BaseAction нет метода Move
// необходимо приведение к типу IAction
// небезопасное приведение
((IAction)baseAction1).Move();   
// безопасное приведение 
if (baseAction1 is IAction action) action.Move();
// или так
IAction baseAction2 = new BaseAction();
baseAction2.Move();

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


class Person : ISchool, IUniversity
{
    public void Study() => Console.WriteLine("Учеба в школе или в университете");
}
interface ISchool
{
    void Study();
}
interface IUniversity
{
    void Study();
}

Класс Person определяет один метод Study(), создавая одну общую реализацию для обоих примененных интерфейсов. И вне зависимости от того, будем ли мы рассматривать объект Person как объект типа ISchool или IUniversity, результат метода будет один и тот же.

Чтобы разграничить реализуемые интерфейсы, надо явным образом применить интерфейс:


class Person : ISchool, IUniversity
{
    void ISchool.Study() => Console.WriteLine("Учеба в школе");
    void IUniversity.Study() => Console.WriteLine("Учеба в университете");
}

Использование:


Person person = new Person();

((ISchool)person).Study();
((IUniversity)person).Study();

Другая ситуация, когда в базовом классе уже реализован интерфейс, но необходимо в производном классе по-своему реализовать интерфейс:


interface IAction
{
    void Move();
}
class BaseAction : IAction
{
    public void Move() =>Console.WriteLine("Move in BaseAction");
}
class HeroAction : BaseAction, IAction
{
    void IAction.Move() => Console.WriteLine("Move in HeroAction");
}

Несмотря на то, что базовый класс BaseAction уже реализовал интерфейс IAction, но производный класс по-своему реализует его. Применение классов:


HeroAction action1 = new HeroAction();
action1.Move();            // Move in BaseAction
((IAction)action1).Move(); // Move in HeroAction

IAction action2 = new HeroAction();
action2.Move();             // Move in HeroAction

Модификаторы доступа

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


IMovable tom = new Person("Tom");
// подписываемся на событие
tom.MoveEvent += () => Console.WriteLine($"{tom.Name} is moving");
tom.Move();

delegate void MoveHandler();    // делегат перемещения
interface IMovable
{
    protected internal void Move();
    protected internal string Name { get;}
    protected internal event MoveHandler MoveEvent;
}
class Person : IMovable
{
    string name;
    // явная реализация события - дополнительно создается переменная
    MoveHandler? moveEvent;
    event MoveHandler IMovable.MoveEvent
    {
        add => moveEvent += value;
        remove => moveEvent -= value;
    }
    // явная реализация свойства - в виде автосвойства
    string IMovable.Name { get => name; }
    public Person(string name) => this.name = name;
    // явная реализация метода
    void IMovable.Move()
    {
        Console.WriteLine($"{name} is walking");
        moveEvent?.Invoke();
    }
}

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

Альтернативный вариант представляет неявная реализация с модификатором public


Person tom = new Person("Tom");
// подписываемся на событие
tom.MoveEvent += () => Console.WriteLine($"{tom.Name} is moving");
tom.Move();

delegate void MoveHandler();

interface IMovable
{
    protected internal void Move();
    protected internal string Name { get;}
    protected internal event MoveHandler MoveEvent;
}
class Person : IMovable
{
    string name;
    // явная реализация события - дополнительно создается переменная
    MoveHandler? moveEvent;
    // неявная реализация события с модификатором public
    public event MoveHandler MoveEvent
    {
        add => moveEvent += value;
        remove => moveEvent -= value;
    }
    // неявная реализация свойства - в виде автосвойства, но с модификатором public
    public string Name { get => name; }
    public Person(string name) => this.name = name;
    // неявная реализация метода, но с модификатором public 
    public void Move()
    {
        Console.WriteLine($"{name} is walking");
        moveEvent?.Invoke();
    }
}

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

Дополнительные материалы

Проверь себя

📋 Тест по теме «Явная реализация интерфейсов» Тест по теме

Практические задания

Лёгкое Ручная проверка Заполните пропуск в коде (1)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

_____ IAction
{
	void Move();
}
class BaseAction : IAction
{
	void IAction.Move() => Console.WriteLine("Move in Base Class");
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (2)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

BaseAction _____ = new BaseAction();

// baseAction1.Move();  // ! Ошибка - в BaseAction нет метода Move
// необходимо приведение к типу IAction
// небезопасное приведение
((IAction)baseAction1).Move();   
// безопасное приведение 
if (baseAction1 is IAction action) action.Move();
// или так
IAction baseAction2 = new BaseAction();
baseAction2.Move();
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (3)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

class Person : ISchool, _____
{
    public void Study() => Console.WriteLine("Учеба в школе или в университете");
}
interface ISchool
{
    void Study();
}
interface IUniversity
{
    void Study();
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (4)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

class Person : _____, IUniversity
{
    void ISchool.Study() => Console.WriteLine("Учеба в школе");
    void IUniversity.Study() => Console.WriteLine("Учеба в университете");
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (5)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

Person person = new Person();

((_____)person).Study();
((IUniversity)person).Study();
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (1)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

interface IAction
{
	void _____();
}
class _____Action : IAction
{
	void IAction.Move() => Console.WriteLine("Move in Base Class");
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (2)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

BaseAction baseAction1 = new BaseAction();

// baseAction1._____();  // ! Ошибка - в BaseAction нет метода Move
// необходимо приведение к типу IAction
// небезопасное приведение
((IAction)baseAction1).Move();   
// безопасное приведение 
if (baseAction1 is IAction _____) action.Move();
// или так
IAction baseAction2 = new BaseAction();
baseAction2.Move();
Войдите, чтобы отправить решение
Среднее Ручная проверка Расставьте строки кода в правильном порядке
+20 XP

Строки кода из примера этого урока перемешаны. Впишите их в правильном порядке, каждую строку — с новой строки.

interface IAction
	void Move();
	void IAction.Move() => Console.WriteLine("Move in Base Class");
}
class BaseAction : IAction
{
{
}
Войдите, чтобы отправить решение
Сложное Ручная проверка Объясните и модифицируйте пример из урока «Явная реализация интерфейсов»
+30 XP

Опишите своими словами, что делает приведённый пример кода из урока «Явная реализация интерфейсов», и предложите одно осмысленное изменение (например, другое входное значение или дополнительное условие). Приведите итоговый код.

interface IAction
{
	void Move();
}
class BaseAction : IAction
{
	void IAction.Move() => Console.WriteLine("Move in Base Class");
}
Войдите, чтобы отправить решение
Сложное Ручная проверка Найдите потенциальную проблему в коде урока «Явная реализация интерфейсов»
+30 XP

Изучите приведённый фрагмент кода и опишите, при каких входных данных или условиях он может сработать не так, как ожидается (граничный случай, отсутствие проверки и т.п.). Предложите исправленный вариант.

BaseAction baseAction1 = new BaseAction();

// baseAction1.Move();  // ! Ошибка - в BaseAction нет метода Move
// необходимо приведение к типу IAction
// небезопасное приведение
((IAction)baseAction1).Move();   
// безопасное приведение 
if (baseAction1 is IAction action) action.Move();
// или так
IAction baseAction2 = new BaseAction();
baseAction2.Move();
Войдите, чтобы отправить решение
Мини-проект Ручная проверка Мини-проект по теме «Явная реализация интерфейсов»
+50 XP

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

Войдите, чтобы отправить решение
Домашнее задание Ручная проверка Домашнее задание по теме «Явная реализация интерфейсов»
+25 XP

Напишите собственную небольшую программу, применяющую материал темы «Явная реализация интерфейсов». Используйте не менее одной конструкции, показанной в примерах урока. Прикрепите код решения и краткое описание того, что он делает.

Войдите, чтобы отправить решение

Обсуждение (0)

Войдите, чтобы оставить комментарий.