Какой хороший пример использования EIMI? - PullRequest
1 голос
/ 23 января 2009

EIMI является явной реализацией члена интерфейса. Так что вместо:

public int SomeValue{get;}

у вас есть

int SomeInterface.SomeValue {get;}

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

Это хороший вариант использования?

Ответы [ 4 ]

7 голосов
/ 23 января 2009

Очень хороший пример - классы общих коллекций .Net.

Например, List<T> реализует 'IList' неявно и IList (не универсальный интерфейс) явно. Это означает, что когда вы используете класс напрямую, вы увидите только специализированные методы, а не те, которые работают с Object.

Допустим, вы создаете экземпляр List<Person>. Если бы IList был реализован неявно, у вас было бы два метода add, напрямую доступных в классе Add (Person item) и Add (Object item), которые нарушат безопасность типов, обеспечиваемую обобщениями. Вызов list.Add ("Foo") скомпилируется очень хорошо, поскольку перегрузка Add (Object) будет выбрана автоматически, а безопасность типов, обеспечиваемая обобщениями, исчезла.

4 голосов
/ 23 января 2009

Да, это хороший вариант использования. В соответствии с C # Language Specification на MSDN:

Явные реализации членов интерфейса служат двум основным целям:

  • Поскольку явные реализации членов интерфейса не доступны через экземпляры класса или структуры, они позволяют исключить реализации интерфейса из открытого интерфейса класса или структуры. Это особенно полезно, когда класс или структура реализуют внутренний интерфейс, который не представляет интереса для потребителя этого класса или структуры.

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

2 голосов
/ 18 февраля 2016

Я хотел бы уточнить, что означает «устранение неоднозначности элементов интерфейса» на примере (Воислав Стойкович, 2-й пример):

public interface IWindow {
   Object GetMenu();
}

public interface IRestaurant {
    Object GetMenu();
}

Два разных интерфейса имеют методы с одинаковыми именами и сигнатурами. Но мы хотим реализовать оба интерфейса:

public sealed class MarioPizzeria : IWindow, IRestaurant  {
    //Explicit inteface member implementation for IWindow      
    Object IWindow.GetMenu();

    //Explicit inteface member implementation for IRestaurant
    Object IRestaurant.GetMenu();

    //An optional method that has nothing to do with an interface
    public Object GetMenu(); 
}

Использование:

MarioPizzeria mp = new MarioPizzeria();
mp.GetMenu(); //MarioPizzeria's public method

//IWindow.GetMenu method
IWindow window = mp;
window.GetMenu();

//IRestaurant.GetMenu method
IRestaurant restaurant = mp;
restaurant.GetMenu();

Интересный факт :

  • Явные реализации членов интерфейса не доступны через экземпляры класса или структуры.
  • Неявные реализации членов интерфейса должны быть всегда публичными.
2 голосов
/ 01 июля 2015

Из книги CLR через C # вы можете найти другую причину использования EIMI: безопасность типов и избегание бокса

Например, вы реализовали интерфейс IComparable:

struct SomeValueType1 : IComparable
{
    private int _v;

    public SomeValueType1(int v)
    {
        _v = v;
    }

    public int CompareTo(object obj)
    {
        return _v - ((SomeValueType1)obj)._v;
    }
}

Посмотрите на реализацию метода CompareTo: Не является безопасным типом. В качестве параметра он получает объект. Если тип объекта не будет SomeValueType1 - он потерпит крах во время выполнения

Использование:

SomeValueType1 svt1 = new SomeValueType1(0);
Object o1 = new Object();
Int32 res = svt1.CompareTo(svt1);
res = svt1.CompareTo(o1);

Третья строка делает бокс из svt1 в Object. 4-я строка выдаст ошибку времени выполнения

Позволяет использовать EIMI:

struct SomeValueType2 : IComparable
{
    private int _v;

    public SomeValueType2(int v)
    {
        _v = v;
    }

    public int CompareTo(SomeValueType2 svt2)
    {
        return _v - svt2._v;
    }

    int IComparable.CompareTo(object obj)
    {
        return CompareTo((SomeValueType2)obj);
    }
}

Использование:

SomeValueType2 svt2 = new SomeValueType2(0);
Object o2 = new Object();
res = svt2.CompareTo(svt2);
res = svt2.CompareTo(o2);

Третья строчка не занимайся боксом! 4-я строка выдаст ошибку времени компиляции

Как писал Джеффри Рихтер в CLR через C # 4-е издание: «Эта дискуссия ясно показывает вам, что EIMI следует использовать с большой осторожностью. Когда многие разработчики впервые узнают об EIMI, они думают, что они крутые и начинают использовать когда это возможно. Не делайте этого! EIMI полезны в некоторых обстоятельствах, но вы должны избегать их, когда это возможно, потому что они делают использование типа очень сложнее. "

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...