Язык программирования C#9 и платформа .NET5
void Draw();}}// IPrintable.csnamespace MiInterfaceHierarchy{interface IPrintable{void Print();void Draw(); // < -- Здесь возможен конфликт имен!}}// IShape.csnamespace MiInterfaceHierarchy{// Множественное наследование интерфейсов. Нормально!interface IShape : IDrawable, IPrintable{int GetNumberOfSides();}}На рис. 8.6 показана текущая иерархия интерфейсов.
Главный вопрос: сколько методов должен реализовывать класс, поддерживающий
? Ответ: в зависимости от обстоятельств. Если вы хотите предоставить простую реализацию методаIShape, тогда вам необходимо реализовать только три члена, как иллюстрируется в следующем типеDraw():Rectangleusing System;namespace MiInterfaceHierarchy{class Rectangle : IShape{public int GetNumberOfSides() => 4;public void Draw() => Console.WriteLine("Drawing...");public void Print() => Console.WriteLine("Printing...");}}Если вы предпочитаете располагать специфическими реализациями для каждого метода
(что в данном случае имеет смысл), то конфликт имен можно устранить с использованием явной реализации интерфейсов, как делается в представленном далее типеDraw():Squarenamespace 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 в своих специальных типах, обеспечивая их бесшовную интеграцию с инфраструктурой.
Интерфейсы IEnumerable и IEnumerator
Прежде чем приступать к исследованию процесса реализации существующих интерфейсов .NET Core, давайте сначала рассмотрим роль интерфейсов
иIEnumerable. Вспомните, что язык C# поддерживает ключевое словоIEnumerator, которое позволяет осуществлять проход по содержимому массива любого типа:foreach// Итерация по массиву элементов.int[] myArrayOfInts = {10, 20, 30, 40};foreach(int i in myArrayOfInts){Console.WriteLine(i);}Хотя может показаться, что данная конструкция подходит только для массивов, на самом деле
разрешено использовать с любым типом, который поддерживает методforeach. В целях иллюстрации создайте новый проект консольного приложения по имениGetEnumerator(). Скопируйте в новый проект файлыCustomEnumeratorиCar.csиз проектаRadio.cs, рассмотренного в главе 7. Не забудьте поменять пространства имен для классов наSimpleException.CustomEnumeratorТеперь вставьте в проект новый класс
(гараж), который хранит набор объектовGarage(автомобиль) внутриCar:System.Array
