Вызов членов интерфейса на уровне объекта
Вызов членов интерфейса на уровне объекта
Теперь, когда у вас есть набор типов, поддерживающих интерфейс Pointy, следующей задачей оказывается доступ я новым функциональным возможностям. Самым простым способом обеспечения доступа к функциональным возможностям данного интерфейса является непосредственный вызов методов на уровне объектов. Например:
static void Main(string[] args) {
// вызов члена Points интерфейса IPointy.
Hexagon hex = new Hexagon();
Console.WriteLine("Вершин: {0}", hex.Points);
Console.ReadLine();
}
Этот подход прекрасно работает в данном конкретном случае, поскольку вы знаете, что тип Hexagon реализует упомянутый интерфейс. Однако в других случаях во время компиляции вы не сможете определить, какие интерфейсы поддерживаются данным типом. Предположим, например, что у нас есть массив из 50 типов, соответствующих Shape, но только некоторые из них поддерживают IPointy. Очевидно, что если вы попытаетесь вызвать свойство Points для типа, в котором IPointy не реализован, вы получите ошибку компиляции. Возникает следующий вопрос: "Как динамически получить информацию о множестве интерфейсов, поддерживаемых данным типом?"
Выяснить во время выполнения, поддерживает ли данный тип конкретный интерфейс можно, например, с помощью явного вызова. Если тип не поддерживает запрошенный интерфейс, вы получите исключение InvalidCastException. Чтобы "изящно" обработать эту возможность, используйте структурированную обработку исключений, например:
static void Main(string[] args) {
…
// Возможный захват исключения InvalidCastException.
Circle с = new Circle ("Lisa");
IPointу itfPt;
try {
itfPt = (IPointy)c;
Console.WriteLine(itfPt.Points);
} catch (InvalidCastException e) {
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
Итак, можно использовать логику try/catch и надеяться на удачу, но лучше еще до вызова членов интерфейса определить, какие интерфейсы поддерживаются. Мы рассмотрим два варианта такой тактики.