TG Telegram Group & Channel
.NET Разработчик | United States America (US)
Create: Update:

День двадцать восьмой. #ЗаметкиНаПолях
Явная реализация интерфейсного метода (EIMI)

class SomeType : IDisposable
{
public void Dispose()
{
Console.WriteLine(“public Dispose”);
}
void IDisposable.Dispose()
{
Console.WriteLine(“IDisposable.Dispose”);
}
}
Если в C# перед именем метода вы ставите имя интерфейса, в котором определён этот метод, то вы создаёте явную реализацию интерфейсного метода. Этому методу нельзя указывать область доступа (private или public), однако компилятор, создавая метаданные для метода, делает его private. Поэтому единственный способ вызвать интерфейсный метод – обратиться через переменную этого интерфейсного типа.

Явная реализация методов интерфейса служит двум главным целям:
1) Поскольку она недоступна через экземпляры класса, это позволяет исключить эти методы из общедоступного интерфейса класса. Это, в частности, полезно, когда класс реализует внутренний интерфейс, который не представляет интереса для пользователей класса.
Например, List<T> реализует IList<T> неявно, а IList (необобщённый интерфейс) явно. Это значит, что, когда вы используете класс напрямую, вы увидите только обобщённые методы и не увидите методы, принимающие Object.
Допустим, вы создали экземпляр List<Person>. Если бы IList был реализован неявно, тогда у вас было бы два метода Add, напрямую доступных из класса: Add(Person item) и Add(Object item), что разрушило бы безопасность типов, предлагаемую обобщениями. Вызов list.Add("Foo") успешно бы скомпилировался, поскольку была бы автоматически выбрана перегруженная версия Add(Object).

2) Явные реализации методов интерфейса позволяют избежать путаницы между двумя реализациями методов с одинаковой сигнатурой. Без этого классам было бы невозможно иметь разные реализации интерфейсных членов с одинаковой сигнатурой и типом возвращаемого значения, а также классам было бы невозможно иметь вообще какие-либо реализации членов интерфейса с одинаковой сигнатурой, но разными типами возвращаемого значения.

В следующем примере класс ресторана реализует два интерфейса для выдачи вариантов меню: на вынос IWindow и «в ресторане» IRestaurant. Эти интерфейсы имеют одинаковые методы GetMenu, но с разными типами возвращаемого значения. Также ресторан может иметь свою собственную реализацию метода GetMenu, не имеющую отношения к интерфейсным методам. Основная программа запрашивает все три метода, приводя экземпляр класса к интерфейсному типу для вызова явных реализаций интерфейсных методов.
using System;

public abstract class Menu { }
public class WindowMenu : Menu { }
public class RestaurantMenu : Menu { }

public interface IWindow { WindowMenu GetMenu(); }
public interface IRestaurant { RestaurantMenu GetMenu(); }

public sealed class Pizzeria : IWindow, IRestaurant
{
//Явная реализация интерфейсного метода для IWindow
WindowMenu IWindow.GetMenu() => new WindowMenu();

//Явная реализация интерфейсного метода для IRestaurant
RestaurantMenu IRestaurant.GetMenu() => new RestaurantMenu();

//Дополнительный открытый метод, не имеющий отношения к интерфейсам
public string GetMenu() => "Public method";
}

class Program
{
static void Main(string[] args)
{
Pizzeria mp = new Pizzeria();
//открытый метод
Console.WriteLine(mp.GetMenu());

//Метод IWindow.GetMenu
var windowMenu = ((IWindow) mp).GetMenu();
Console.WriteLine(windowMenu.ToString());

//Метод IRestaurant.GetMenu
var restaurantMenu = ((IRestaurant) mp).GetMenu();
Console.WriteLine(restaurantMenu.ToString());

Console.ReadLine();
}
}

Источник: Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 13.

День двадцать восьмой. #ЗаметкиНаПолях
Явная реализация интерфейсного метода (EIMI)
class SomeType : IDisposable
{
public void Dispose()
{
Console.WriteLine(“public Dispose”);
}
void IDisposable.Dispose()
{
Console.WriteLine(“IDisposable.Dispose”);
}
}
Если в C# перед именем метода вы ставите имя интерфейса, в котором определён этот метод, то вы создаёте явную реализацию интерфейсного метода. Этому методу нельзя указывать область доступа (private или public), однако компилятор, создавая метаданные для метода, делает его private. Поэтому единственный способ вызвать интерфейсный метод – обратиться через переменную этого интерфейсного типа.

Явная реализация методов интерфейса служит двум главным целям:
1) Поскольку она недоступна через экземпляры класса, это позволяет исключить эти методы из общедоступного интерфейса класса. Это, в частности, полезно, когда класс реализует внутренний интерфейс, который не представляет интереса для пользователей класса.
Например, List<T> реализует IList<T> неявно, а IList (необобщённый интерфейс) явно. Это значит, что, когда вы используете класс напрямую, вы увидите только обобщённые методы и не увидите методы, принимающие Object.
Допустим, вы создали экземпляр List<Person>. Если бы IList был реализован неявно, тогда у вас было бы два метода Add, напрямую доступных из класса: Add(Person item) и Add(Object item), что разрушило бы безопасность типов, предлагаемую обобщениями. Вызов list.Add("Foo") успешно бы скомпилировался, поскольку была бы автоматически выбрана перегруженная версия Add(Object).

2) Явные реализации методов интерфейса позволяют избежать путаницы между двумя реализациями методов с одинаковой сигнатурой. Без этого классам было бы невозможно иметь разные реализации интерфейсных членов с одинаковой сигнатурой и типом возвращаемого значения, а также классам было бы невозможно иметь вообще какие-либо реализации членов интерфейса с одинаковой сигнатурой, но разными типами возвращаемого значения.

В следующем примере класс ресторана реализует два интерфейса для выдачи вариантов меню: на вынос IWindow и «в ресторане» IRestaurant. Эти интерфейсы имеют одинаковые методы GetMenu, но с разными типами возвращаемого значения. Также ресторан может иметь свою собственную реализацию метода GetMenu, не имеющую отношения к интерфейсным методам. Основная программа запрашивает все три метода, приводя экземпляр класса к интерфейсному типу для вызова явных реализаций интерфейсных методов.
using System;

public abstract class Menu { }
public class WindowMenu : Menu { }
public class RestaurantMenu : Menu { }

public interface IWindow { WindowMenu GetMenu(); }
public interface IRestaurant { RestaurantMenu GetMenu(); }

public sealed class Pizzeria : IWindow, IRestaurant
{
//Явная реализация интерфейсного метода для IWindow
WindowMenu IWindow.GetMenu() => new WindowMenu();

//Явная реализация интерфейсного метода для IRestaurant
RestaurantMenu IRestaurant.GetMenu() => new RestaurantMenu();

//Дополнительный открытый метод, не имеющий отношения к интерфейсам
public string GetMenu() => "Public method";
}

class Program
{
static void Main(string[] args)
{
Pizzeria mp = new Pizzeria();
//открытый метод
Console.WriteLine(mp.GetMenu());

//Метод IWindow.GetMenu
var windowMenu = ((IWindow) mp).GetMenu();
Console.WriteLine(windowMenu.ToString());

//Метод IRestaurant.GetMenu
var restaurantMenu = ((IRestaurant) mp).GetMenu();
Console.WriteLine(restaurantMenu.ToString());

Console.ReadLine();
}
}

Источник: Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 13.
👍2


>>Click here to continue<<

.NET Разработчик




Share with your best friend
VIEW MORE

United States America Popular Telegram Group (US)