Яка різниця між реалізацією інтерфейсу явно чи неявно?


64

У Visual Studio я можу клацнути правою кнопкою миші інтерфейс і вибрати Інтерфейс реалізації або Явно реалізувати інтерфейс.

Знімок екрану візуальної студії

public class Test : ITest
{
    public string Id // Generated by Implement Interface
    {
        get { throw new NotImplementedException(); }
    }

    string ITest.Id // Generated by Implement Interface Explicitly
    {
        get { throw new NotImplementedException(); }
    }
}

Єдина відмінність, яку я бачу між ними, полягає в тому, що ім'я інтерфейсу додається до властивостей інтерфейсу та методів, коли вони створюються, якщо ви вирішите явно реалізувати інтерфейс.

Я вважаю, що це робить код трохи читабельнішим, оскільки я бачу, звідки береться цей метод / властивість, однак чи має це значення будь-яке значення в тому, як використовується клас чи компілюється клас? І чи дійсно це важливо, якщо я реалізую свої інтерфейси неявно або явно?

Відповіді:


51

Перевірте головну відповідь від Ендрю Барретта щодо "неявної та явної реалізації інтерфейсу" на SO .

В основному:

  • Неявне: ви отримуєте доступ до методів та властивостей інтерфейсу так, ніби вони були частиною класу.
  • Явне: ви можете отримати доступ до методів та властивостей лише під час обробки класу як реалізованого інтерфейсу.

Приклади коду:

Неявне:

Test t = new Test();
t.Id; // OK
((ITest)t).Id; // OK

Явне:

Test t = new Test();
t.Id; // Not OK
((ITest)t).Id; // OK

З точки зору "коли" ви повинні явно реалізувати інтерфейс, це коли ваш клас вже має метод з тією ж підписом, що і один із методів вашого інтерфейсу, або коли ваш клас реалізує кілька інтерфейсів, які ділять методи з однаковими підписами але несумісні договори.


1
Я також знайшов явну реалізацію корисною для свого роду "прихованого" інтерфейсу з небезпечними операціями. Це також робить виклики до тих методів більше виділятися, що добре для небезпечних речей.
Tamás Szelei

Слід також зазначити, що використання явних інтерфейсів коштує для продуктивності, оскільки йому потрібно встановити / розблокувати об'єкт у будь-який час, коли ви посилаєтесь на властивість / метод. Через це краще, якщо можливо, неявні інтерфейси
Рейчел

3
@Rachel: Наскільки мені відомо, вартість продуктивності стосується лише типів цінності.
Жорсткий

8

Існує також різниця в тому, як ви викликаєте метод.

Використовуючи явну реалізацію інтерфейсу, ви повинні використовувати тип інтерфейсу, щоб викликати цю конкретну реалізацію.

Отже, для виклику коду вам потрібно буде використовувати змінну типу ITestдля доступу ITest.Id.

Стаття Явна реалізація інтерфейсу (посібник з програмування C #) на MSDN є хорошим прикладом.


4

Це дозволяє реалізувати два інтерфейси, які визначають один і той же метод. Однак якщо ви явно реалізуєте інтерфейс, доступ до методів можна отримати лише тоді, коли змінна буде введена в цей явний інтерфейс.

Див.: Посібник з явного інтерфейсу


4

EDIT: Це не повинно змінювати. Ви не повинні робити це, якщо ваш клас не реалізує два інтерфейси з однаковими властивостями, оскільки вам доведеться передати відповідний інтерфейс, перш ніж ви зможете отримати доступ до учасника:

public interface ITest
{
    string Id { get; }
}

public interface IAlsoTest
{
    string Id { get; }
}

public interface ITestToo
{
    int Id { get; }
}

public class Test : ITest, IAlsoTest
{
    // Valid implicit implementation of BOTH interfaces
    public string Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestSeparately : ITest, ITestToo
{
    // This way we can do different things depending
    // on which interface the callee called from.
    string ITest.Id
    {
        get { throw new NotImplementedException(); }
    }

    int ITestToo.Id
    {
        get { throw new NotImplementedException(); }
    }
}

public class TestOuch
{
    public void DoStuff()
    {
        var ts = new TestSeparately();

        // Works
        Console.WriteLine(((ITest)ts).Id);

        // Works
        Console.WriteLine(((ITestToo)ts).Id);

        // Not valid! Which one did we want to call?
        Console.WriteLine(ts.Id);
    }
}

Приклад використання справедливий, коли ви явно реалізуєте член інтерфейсу, навіть якщо ви використовуєте лише один інтерфейс (який я завжди забуваю: S), тому я намагався б уникати явної реалізації, коли це можливо, оскільки це приховатиме членів класу, якщо вони ' повторно не приведений до потрібного інтерфейсу (що досить заплутано).


3

Виходячи з відповіді Джалаяна,

  • Неявне: ви отримуєте доступ до методів та властивостей інтерфейсу так, ніби вони були частиною класу.
  • Явне: ви можете отримати доступ до методів та властивостей лише під час обробки класу як реалізованого інтерфейсу.

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.