Язык программирования C#9 и платформа .NET5
interface IRegularPointy : IPointy{int SideLength { get; set; }int NumberOfSides { get; set; }int Perimeter => SideLength * NumberOfSides;// Статические члены также разрешены в версии C# 8static string ExampleProperty { get; set; }static IRegularPointy() => ExampleProperty = "Foo";}Статические конструкторы не должны иметь параметры и могут получать доступ только к статическим свойствам и методам. Для обращения к статическому свойству интерфейса добавьте к операторам верхнего уровня следующий код:
Console.WriteLine($"Example property: {IRegularPointy.ExampleProperty}");IRegularPointy.ExampleProperty = "Updated";Console.WriteLine($"Example property: {IRegularPointy.ExampleProperty}");Обратите внимание, что к статическому свойству необходимо обращаться через интерфейс, а не переменную экземпляра.
Использование интерфейсов в качестве параметров
Учитывая, что интерфейсы являются допустимыми типами, можно строить методы, которые принимают интерфейсы в качестве параметров, как было проиллюстрировано на примере метода
ранее в главе. Предположим, что вы определили в текущем примере еще один интерфейс по имениCloneMe():IDraw3Dnamespace CustomInterfaces{// Моделирует способность визуализации типа в трехмерном виде.public interface IDraw3D{void Draw3D();}}Далее сконфигурируйте две из трех фигур (
иCircle) с целью поддержки нового поведения:Hexagon// Circle поддерживает IDraw3D.class ThreeDCircle : Circle, IDraw3D{...public void Draw3D()=> Console.WriteLine("Drawing Circle in 3D!"); }}// Hexagon поддерживает IPointy и IDraw3D.class Hexagon : Shape, IPointy, IDraw3D{...public void Draw3D()=> Console.WriteLine("Drawing Hexagon in 3D!");}На рис. 8.2 показана обновленная диаграмма классов в Visual Studio.
Теперь если вы определите метод, принимающий интерфейс
в качестве параметра, тогда ему можно будет передавать по существу любой объект, реализующийIDraw3D. Попытка передачи типа, не поддерживающего необходимый интерфейс, приводит ошибке на этапе компиляции. Взгляните на следующий метод, определенный в классеIDraw3D:Program// Будет рисовать любую фигуру, поддерживающую IDraw3D.static void DrawIn3D(IDraw3D itf3d){Console.WriteLine("-> Drawing IDraw3D compatible type");itf3d.Draw3D();}Далее вы можете проверить, поддерживает ли элемент в массиве
новый интерфейс, и если поддерживает, то передать его методуShapeна обработку:DrawIn3D()Console.WriteLine("***** Fun with Interfaces *****\n");Shape[] myShapes = { new Hexagon(), new Circle(),new Triangle("Joe"), new Circle("JoJo") } ;for(int i = 0; i < myShapes.Length; i++){// Can I draw you in 3D?if (myShapes[i] is IDraw3D s){DrawIn3D(s);}}Ниже представлен вывод, полученный из модифицированной версии приложения. Обратите внимание, что в трехмерном виде отображается только объект
, т.к. все остальные члены массиваHexagonне реализуют интерфейсShape:IDraw3D***** Fun with Interfaces *****...-> Drawing IDraw3D compatible typeDrawing Hexagon in 3D!Использование интерфейсов в качестве возвращаемых значений
Интерфейсы могут также применяться в качестве типов возвращаемых значений методов. Например, можно было бы написать метод, который получает массив объектов
и возвращает ссылку на первый элемент, поддерживающийShape:IPointy// Этот метод возвращает первый объект в массиве,// который реализует интерфейс IPointy.static IPointy FindFirstPointyShape(Shape[] shapes){foreach (Shape s in shapes){if (s is IPointy ip)
