views:

595

answers:

1

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?

+4  A: 

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:

  • Foo.Clone()
  • Bar.Clone()
  • ICloneable.Clone()

all use the correct CloneCore() implementation for the concrete type.

Marc Gravell