namespace MiInterfaceHierarchy

{

  class Rectangle : IShape

  {

    public int GetNumberOfSides() => 4;

    public void Draw() => Console.WriteLine("Drawing...");

    public void Print() => Console.WriteLine("Printing...");

  }

}

Если вы предпочитаете располагать специфическими реализациями для каждого метода Draw() (что в данном случае имеет смысл), то конфликт имен можно устранить с использованием явной реализации интерфейсов, как делается в представленном далее типе Square:

namespace MiInterfaceHierarchy

{

  class Square : IShape

  {

    // Использование явной реализации для устранения

    // конфликта имен членов.

    void IPrintable.Draw()

    {

      // Вывести на принтер...

    }

    void IDrawable.Draw()

    {

      // Вывести на экран...

    }

    public void Print()

    {

      // Печатать...

    }

    public int GetNumberOfSides() => 4;

  }

}

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

Однако имейте в виду, что интерфейсы являются фундаментальным аспектом .NET Core. Независимо от типа разрабатываемого приложения (веб-приложение, настольное приложение с графическим пользовательским интерфейсом, библиотека доступа к данным и т.п.) работа с интерфейсами будет составной частью этого процесса. Подводя итог, запомните, что интерфейсы могут быть исключительно полезны в следующих ситуациях:

• существует единственная иерархия, в которой общее поведение поддерживается только подмножеством производных типов;

• необходимо моделировать общее поведение, которое встречается в нескольких иерархиях, не имеющих общего родительского класса кроме System.Object.

Итак, вы ознакомились со спецификой построения и реализации специальных интерфейсов. Остаток главы посвящен исследованию нескольких предопределенных интерфейсов, содержащихся в библиотеках базовых классов .NET Core. Как будет показано, вы можете реализовывать стандартные интерфейсы .NET Core в своих специальных типах, обеспечивая их бесшовную интеграцию с инфраструктурой. 

<p id="AutBody_Root338">Интерфейсы IEnumerable и IEnumerator</p>

Прежде чем приступать к исследованию процесса реализации существующих интерфейсов .NET Core, давайте сначала рассмотрим роль интерфейсов IEnumerable и IEnumerator. Вспомните, что язык C# поддерживает ключевое слово foreach, которое позволяет осуществлять проход по содержимому массива любого типа:

// Итерация по массиву элементов.

int[] myArrayOfInts = {10, 20, 30, 40};

foreach(int i in myArrayOfInts)

{

  Console.WriteLine(i);

}

Хотя может показаться, что данная конструкция подходит только для массивов, на самом деле foreach разрешено использовать с любым типом, который поддерживает метод GetEnumerator(). В целях иллюстрации создайте новый проект консольного приложения по имени CustomEnumerator. Скопируйте в новый проект файлы Car.cs и Radio.cs из проекта SimpleException, рассмотренного в главе 7. Не забудьте поменять пространства имен для классов на CustomEnumerator.

Теперь вставьте в проект новый класс Garage (гараж), который хранит набор объектов Car (автомобиль) внутри System.Array:

using System.Collections;

namespace CustomEnumerator

{

  // Garage содержит набор объектов Car.

  public class Garage

  {

    private Car[] carArray = new Car[4];

    // При запуске заполнить несколькими объектами Car.

    public Garage()

    {

      carArray[0] = new Car("Rusty", 30);

      carArray[1] = new Car("Clunker", 55);

      carArray[2] = new Car("Zippy", 30);

      carArray[3] = new Car("Fred", 30);

    }

  }

}

В идеальном случае было бы удобно проходить по внутренним элементам объекта Garage с применением конструкции foreach как в ситуации с массивом значений данных:

using System;

using CustomEnumerator;

// Код выглядит корректным...

Перейти на страницу:

Похожие книги