为什么要使用显式接口实现来调用受保护的方法?
在 codeplex,我发现有一个类显式实现接口是很常见的。 然后,显式实现的方法/属性调用另一个具有相同名称的“受保护虚拟”方法/属性。
例如,
public class MvcHandler : IHttpHandler, IRequiresSessionState
{
protected virtual bool IsReusable
{
get
{
return false;
}
}
bool IHttpHandler.IsReusable
{
get
{
return IsReusable;
}
}
}
我现在确定这种编程有什么好处。 对我来说,我更喜欢隐式实现 IHttpHandler 接口。
我猜作者只是不希望 MvcHandler 有一个公共属性 IsResuable。 仅当 MvcHandler 实例被视为 IHttpHandler 时才能使用属性 IsReusable。 尽管如此,我还是不确定作者为什么要这样做。
有人知道这种接口实现方式的更多好处吗?
When browsing ASP.NET MVC source code in codeplex, I found it is common to have a class explicitly implementing interface. The explicitly implemented method/property then invoke another "protected virtual" method/property with same name.
For example,
public class MvcHandler : IHttpHandler, IRequiresSessionState
{
protected virtual bool IsReusable
{
get
{
return false;
}
}
bool IHttpHandler.IsReusable
{
get
{
return IsReusable;
}
}
}
I'm now sure what's the benefit of this kind of programming. For me, I prefer to just implicitly implement the interface IHttpHandler.
I guess the author just don't want MvcHandler has a public property IsResuable. The property IsReusable can only be used when instance of MvcHandler is treated as a IHttpHandler. Still, I'm not sure why the author what this way.
Anybody know more benefits about this style of interface implementation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
嗯,不是特定于 MVC,但这种方法允许您保持核心公共 API 干净。 如果存在不同接口/等具有相同名称和名称的风险,它也很有用。 签名,但含义不同。 事实上,这种情况很少见。
它还允许您提供一个实现,您希望在子类中更改返回类型:(
为简单起见选择
ICloneable
- 不要因为它是一个定义不明确的接口这一事实而烦恼。一个更好的例子是像DbCommand
等,它可以做到这一点 - 但这很难在一个简短的例子中展示)如果我们使用了公共虚拟方法,我们将无法
覆盖
它并在基类中使用new
,因为您不能同时执行这两种操作:使用受保护的虚拟方法,任何用法:
都使用具体类型的正确
CloneCore()
实现。Well, not specific to MVC, but this approach allows you to keep the core public API clean. It is also useful if there is ever a risk of different interfaces / etc having the same name & signature, but different meaning. In reality this is rare.
It also allows you to provide an implementation where you want the return type to change in subclasses:
(
ICloneable
chosen for simplicity - don't get hung up on the fact that it is a poorly defined interface... a better example would have been things likeDbCommand
etc, which do this - but that is harder to show in a short example)If we had used a public virtual method, we wouldn't be able to
override
it and usenew
in the base-class, as you aren't allowed to do both:Using the protected virtual approach, any usage:
all use the correct
CloneCore()
implementation for the concrete type.如果一个类显式实现了 IFoo.Bar,并且派生类需要 IFoo.Bar 来执行不同的操作,则派生类将无法调用基类该方法的类实现。 不重新实现
IFoo.Bar
的派生类可以通过((IFoo)this).Bar()
调用基类实现,但如果派生类重新实现 IFoo.Bar(因为它必须这样做才能改变其行为)上述调用将转到派生类重新实现,而不是基类实现。 即使((IFoo)(BaseType)this).bar
也无济于事,因为将引用强制转换为接口类型将丢弃有关该引用类型的任何信息(而不是该引用的类型)实例实例)被强制转换。显式接口实现除了调用受保护的方法之外什么都不做,可以避免此问题,因为派生类可以通过重写虚拟方法来更改接口方法的行为,同时保留调用其认为合适的基实现的能力。 恕我直言,C# 应该有一个显式接口实现,生成一个具有 CLS 兼容名称的虚拟方法,因此用 C# 编写显式实现 IFoo.Bar 的类的派生类的人可以说
override void IFoo.Bar
,而用其他语言编写的人可能会说,例如Overrides Sub Explicit_IFoo_Bar()
; 因为任何派生类都可以重新实现IFoo.Bar
,并且任何不重新实现IFoo.Bar
的派生类都可以自行调用它,所以我不这样做我们看不到密封显式实现有任何有用的目的。顺便说一句,在 vb.net 中,正常模式只是
Protected Overridable Sub IFoo_Bar() Implements IFoo.Bar
,而不需要单独的虚拟方法。If a class implements
IFoo.Bar
explicitly, and a derived class needsIFoo.Bar
to do something different, there will be no way for the derived class to call the base-class implementation of that method. A derived class which does not re-implementIFoo.Bar
could call the base-class implementation via((IFoo)this).Bar()
, but if the derived class re-implementsIFoo.Bar
(as it would have to in order to change its behavior) the aforementioned call would go to the derived-class re-implementation, rather than the base-class implementation. Even((IFoo)(BaseType)this).bar
wouldn't help, since casting a reference to an interface type will discard any information about the type of the reference (as opposed to the type of the instance instance) that was cast.Having an explicit interface implementation do nothing but call a protected method avoids this problem, since a derived class can change the behavior of the interface method by overriding the virtual method, while retaining the ability to call the base implementation as it sees fit. IMHO, C# should have had an explicit interface implementation produce a virtual method with a CLS-compliant name, so someone writing in C# a derivative of a class that explicitly implemented
IFoo.Bar
could sayoverride void IFoo.Bar
, and someone writing in some other language could say, e.g.Overrides Sub Explicit_IFoo_Bar()
; since any derived class can re-implementIFoo.Bar
, and since any derived class which doesn't re-implementIFoo.Bar
can call it on itself, I don't see that there's any useful purpose to having the explicit implementation be sealed.Incidentally, in vb.net, the normal pattern would simply be
Protected Overridable Sub IFoo_Bar() Implements IFoo.Bar
, without need for a separate virtual method.原因 1 的示例:
sample for reason 1: