Разница между неявной и явной реализацией интерфейсов 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.
разница в том, что можно наследовать класс от нескольких интерфейсов. Эти интерфейсы могут иметь идентичные сигнатуры методов. Явная реализация позволяет изменить вашу реализацию в соответствии с тем, какой интерфейс использовался для ее вызова.
явная реализация интерфейса, где реализация скрыта, если вы явно не литой, является наиболее полезным, когда интерфейс является ортогональной к функции класса. То есть поведенчески не связаны .
например, если ваш класс Person и интерфейс ISerializable, для кого-то, кто имеет дело с атрибутами Person, не имеет смысла видеть что-то странное под названием "GetObjectData" через Intellisense. Поэтому вы можете явно захотеть реализовать интерфейс.
с другой стороны, если ваш класс person реализует IAddress, имеет смысл видеть такие члены, как AddressLine1, ZipCode и т. д. На экземплярах Person напрямую (неявная реализация).