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?
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 like DbCommand
etc, which do this - but that is harder to show in a short example)
class Foo : ICloneable
{
public Foo Clone() { return CloneCore(); }
object ICloneable.Clone() { return CloneCore(); }
protected virtual Foo CloneCore() { ... }
}
class Bar : Foo
{
protected override Foo CloneCore() { ... }
public new Bar Clone() { return (Bar)CloneCore(); }
}
If we had used a public virtual method, we wouldn't be able to override
it and use new
in the base-class, as you aren't allowed to do both:
class A
{
public virtual A SomeMethod() { ... }
}
class B : A
{
public override A SomeMethod() { ... }
//Error 1 Type 'B' already defines a member called 'SomeMethod' with the same parameter types
public new B SomeMethod() { ... }
}
Using the protected virtual approach, any usage:
all use the correct CloneCore()
implementation for the concrete type.