Один из способов выяснить во время выполнения, поддерживает ли тип конкретный интерфейс, предусматривает применение явного приведения. Если тип не поддерживает запрашиваемый интерфейс, то генерируется исключение InvalidCastException
...
// Перехватить возможное исключение InvalidCastException.
Circle c = new Circle("Lisa");
IPointy itfPt = null;
try
{
itfPt = (IPointy)c;
Console.WriteLine(itfPt.Points);
}
catch (InvalidCastException e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine();
Хотя можно было бы применить логику try/catch
Получение ссылок на интерфейсы: ключевое слово as
Для определения, поддерживает ли данный тип тот или иной интерфейс, можно использовать ключевое слово as
null. Таким образом, перед продолжением в коде необходимо реализовать проверку на предмет null:...
// Можно ли hex2 трактовать как IPointy?
Hexagon hex2 = new Hexagon("Peter");
IPointy itfPt2 = hex2 as IPointy;
if(itfPt2 != null)
{
Console.WriteLine("Points: {0}", itfPt2.Points);
}
else
{
Console.WriteLine("OOPS! Not pointy..."); // He реализует IPointy
}
Console.ReadLine();
Обратите внимание, что когда применяется ключевое слово as
try/catch, т.к. если ссылка не является null, то известно, что вызов происходит для действительной ссылки на интерфейс.Получение ссылок на интерфейсы: ключевое слово is (обновление в версии 7.0)
Проверить, реализован ли нужный интерфейс, можно также с помощью ключевого слова is
false. В случае предоставления в операторе имени переменной ей назначается надлежащий тип, что устраняет необходимость в проверке типа и выполнении приведения. Ниже показан обновленный предыдущий пример:Console.WriteLine("***** Fun with Interfaces *****\n");
...
if(hex2 is IPointy itfPt3)
{
Console.WriteLine("Points: {0}", itfPt3.Points);
}
else
{
Console.WriteLine("OOPS! Not pointy...");
}
Console.ReadLine();
Стандартные реализации (нововведение в версии 8.0)
Как упоминалось ранее, в версии C# 8.0 методы и свойства интерфейса могут иметь стандартные реализации. Добавьте к проекту новый интерфейс по имени IRegularPointy
namespace CustomInterfaces
{
interface IRegularPointy : IPointy
{
int SideLength { get; set; }
int NumberOfSides { get; set; }
int Perimeter => SideLength * NumberOfSides;
}
}
Добавьте к проекту новый файл класса по имени Square.cs
Shape и реализуйте интерфейс IRegularPointy:namespace CustomInterfaces
{
class Square: Shape,IRegularPointy
{
public Square() { }
public Square(string name) : base(name) { }
// Метод Draw() поступает из базового класса Shape
public override void Draw()
{
Console.WriteLine("Drawing a square");
}
// Это свойство поступает из интерфейса IPointy
public byte Points => 4;
// Это свойство поступает из интерфейса IRegularPointy.
public int SideLength { get; set; }