我看到了这段代码并提出了一些问题:
public class MyClassB : MyClassA, IMyClass
{
void IMyClass.InsertUser(User user) { }
}
为什么他们必须在接口IMyClass
前加上前缀,而不仅仅是:
void InsertUser(User user) { }
或者可能
void new InsertUser(User user)
此外,因为您继承自MyClassA
(实现接口IMyClass
),为什么我们会看到:
public class MyClassB : MyClassA, IMyClass { }
答案 0 :(得分:10)
只需
void InsertUser(User user)
不起作用,因为它会声明一个私有方法。带前缀的版本称为explicit interface implementation。它仅通过接口使该方法可用。其主要用途之一是允许您实现包含相同方法的多个接口。最好的例子是IEnumerable<T>
扩展IEnumerable
- 两者都有GetEnumerator()
方法,但返回类型不同。你通常会这样做:
public class Foo : IEnumerable<T>
{
// Implicit interface implementation
public IEnumerator<T> GetEnumerator()
{
// Real work
}
// Explicit interface implementation
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator(); // Calls method above
}
}
至于重新声明界面,如果您还重新实现接口,那么这是必要的,它看起来就像你在这里做的那样。我的猜测是MyClassA
用非虚方法(或显式)实现接口,这意味着它不能在派生类中重写...所以要重新实现接口,你必须重新声明它
我个人试图在可能的情况下避免这种情况 - 当被调用的方法完全依赖于你“碰巧”看到有问题的对象时,它会导致各种问题。 MyClassA
最好使用MyClassB
覆盖的虚拟方法实现接口。
答案 1 :(得分:1)
您的第一个问题已经回答了。以下是其他人:
void new InsertUser(User user)
这将创建一个InsertUser的新实现,它将隐藏基类中的那个。所以:
myClassBInstance.InsertUser(user);
会调用MyClassB.InsertUser(),而
MyClassA myClassAInstance = myClassBInstance;
myClassAInstance.InsertUser(user);
将调用MyClassA.InsertUser()。
这与显式接口实现形成对比,显式接口实现仅可通过接口使用。然后
IMyClassA myIClassAInstance = myClassBInstance;
myIClassAInstance.InsertUser(user);
将调用MyClassB.InsertUser,而:
myClassBInstance.InsertUser(user);
...会调用MyClassA.InsertUser()。
现在,对于最后一个问题:如果MyClassA实现了IMyClass,声明:
public class MyClassB : MyClassA, IMyClass { }
实际上是多余的(但合法的)。正如您所想,MyClassB继承了MyClassA的接口。声明
public class MyClassB : MyClassA { }
等同。
答案 2 :(得分:0)
这是一个explicit interface implementation。
很有可能是这样的,因为代码让VS向导为他/她。这是一个允许消除具有其他类似签名的方法的功能。
答案 3 :(得分:0)
前缀表示已明确实现接口。当你有一个类的实例时,你将无法直接调用该方法,而是必须将实例强制转换为接口才能调用该方法。
你有两个原因可以做到这一点。首先,您要实现多个具有相同方法名称但需要以不同方式运行的接口。第二种是当你需要实现一个接口但不希望这些方法通常可供用户使用,除非他们明确地想要它们
答案 4 :(得分:0)
您必须键入接口名称或新建接口名称的原因是MyClassA还使用IMyClass接口,这意味着它实现了InsertCustomer方法。