Разница между неявной и явной реализацией интерфейсов C# [дубликат]

этот вопрос уже есть ответ здесь:

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

когда вы производите класс от интерфейс, intellisense предлагает вам сделать оба.

но, какая разница?

8 ответов


еще один аспект этого:

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

Если это явно реализовано, клиенты должны будут привести ваш класс к интерфейсу, прежде чем получить доступ к членам. Вот пример явной реализации:

    interface Animal
{
    void EatRoots();
    void EatLeaves();
}

interface Animal2
{
    void Sleep();
}


class Wombat : Animal, Animal2
{
    // Implicit implementation of Animal2
    public void Sleep()
    {
    }

    // Explicit implementation of Animal
    void Animal.EatRoots()
    {

    }

    void Animal.EatLeaves()
    {
    }

}

код клиента

Wombat w = new Wombat();
w.Sleep();
w.EatRoots();   // This will cause a compiler error because it's explicitly implemented
((Animal)w).EatRoots();  // This will compile

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

это также полезно если:

  • существует конфликт между интерфейсом Foo метод и ваш собственный тип Foo метод, и они означают разные вещи
  • существует конфликт сигнатур между другими интерфейсами

типичным примером последнего пункта является IEnumerable<T>, которая имеет GetEnumerator() метод на двух уровнях в иерархии интерфейса - обычно реализуется типизированный (IEnumerator<T>) версия, использующая неявную реализацию, и нетипизированная (IEnumerator) версия с использованием явной реализации.


здесь разница в простом английском языке:

Предположим, у вас есть интерфейс Machine, который имеет функцию Run(), и другой интерфейс Animal, который также имеет функцию под названием Run(). Конечно, когда машина работает, мы говорим о ее запуске, но когда животное работает, мы говорим о том, что оно движется. Итак, что происходит, когда у вас есть объект, давайте назовем его Aibo что это Machine и Animal? (Кстати, Айбо-механическая собака.) Когда Aibo работает, он запускается, или же передвигаться? Явная реализация интерфейса позволяет вам сделать это различие:

interface Animal
{
    void Run();
}
interface Machine
{
    void Run();
}

class Aibo : Animal, Machine
{
    void Animal.Run()
    {
        System.Console.WriteLine("Aibo goes for a run.");
    }
    void Machine.Run()
    {
        System.Console.WriteLine("Aibo starting up.");
    }
}
class Program
{
    static void Main(string[] args)
    {
        Aibo a = new Aibo();
        ((Machine)a).Run();
        ((Animal)a).Run();
    }
}

здесь загвоздка в том, что я не могу просто позвонить a.Run() потому что обе мои реализации функции явно прикреплены к интерфейсу. Это имеет смысл, потому что в противном случае, как бы complier знал, какой из них позвонить? Вместо этого, если я хочу позвонить


Explicit поставит IInterfaceName. в передней части всех реализаций интерфейса. Это полезно, если вам нужно реализовать два интерфейса, которые содержат имена/подписи конфликтуют.

Подробнее здесь.


явно реализовать ставит полное имя на имя функции рассмотрим этот код

    public interface IamSam
    {
        int foo();
        void bar();
    }

    public class SamExplicit : IamSam
    {
        #region IamSam Members

        int IamSam.foo()
        {
            return 0;
        }

        void IamSam.bar()
        {

        }

        string foo()
        {
            return "";
        }
        #endregion
    }

    public class Sam : IamSam
    {
        #region IamSam Members

        public int foo()
        {
            return 0;
        }

        public void bar()
        {

        }

        #endregion
    }

IamSam var1;
var1.foo()  returns an int.
SamExplicit var2;
var2.foo() returns a string.
(var2 as IamSam).foo() returns an int.

вот вы идете, прямо из MSDN


разница в том, что можно наследовать класс от нескольких интерфейсов. Эти интерфейсы могут иметь идентичные сигнатуры методов. Явная реализация позволяет изменить вашу реализацию в соответствии с тем, какой интерфейс использовался для ее вызова.


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

например, если ваш класс Person и интерфейс ISerializable, для кого-то, кто имеет дело с атрибутами Person, не имеет смысла видеть что-то странное под названием "GetObjectData" через Intellisense. Поэтому вы можете явно захотеть реализовать интерфейс.

с другой стороны, если ваш класс person реализует IAddress, имеет смысл видеть такие члены, как AddressLine1, ZipCode и т. д. На экземплярах Person напрямую (неявная реализация).