【发布时间】:2010-10-17 07:02:39
【问题描述】:
显式实现接口和实现接口有什么区别。
当您从接口派生类时,intellisense 建议您两者都做。
但是,有什么区别呢?
【问题讨论】:
显式实现接口和实现接口有什么区别。
当您从接口派生类时,intellisense 建议您两者都做。
但是,有什么区别呢?
【问题讨论】:
另一方面:
如果您隐式实现,则意味着您的类的用户可以访问接口成员,而无需他们进行强制转换。
如果它是显式实现的,则客户端必须先将您的类转换为接口,然后才能访问成员。 下面是一个显式实现的例子:
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 是一只机械狗。)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(),因为我的两个函数实现都显式附加到一个接口。这是有道理的,否则编译器怎么知道该调用哪一个呢?相反,如果我想直接在 Aibo 上调用 Run() 函数,我将不得不也在没有显式接口的情况下实现该函数。
【讨论】:
显式将IInterfaceName。在所有接口实现的前面。如果您需要实现两个包含冲突的名称/签名的接口,这将非常有用。
更多信息here.
【讨论】:
显式实现将完全限定名称放在函数名上考虑此代码
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 属性的人通过 Intellisense 看到名为“GetObjectData”的奇怪东西就没有多大意义。因此,您可能希望显式实现该接口。
另一方面,如果您的 person 类碰巧实现了 IAddress,那么直接在 Person 实例上查看 AddressLine1、ZipCode 等成员(隐式实现)非常有意义。
【讨论】: