Why to Use Explicit Interface Implementation To Invoke a Protected Method?

后端 未结 3 726
南笙
南笙 2021-01-02 05:29

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 in

相关标签:
3条回答
  • 2021-01-02 06:02
    1. When a member is explicitly implemented, it cannot be accessed through a class instance, but only through an instance of the interface. reference : Explicit Interface Implementation Tutorial
    2. As my experience if interface implementer explicitly implement an interface he will receive compiler error after you drop a method from interface while he will not notify if he/she implicitly implement it and the method will remain in the code.

    sample for reason 1:

    public interface IFoo
    {
        void method1();
        void method2();
    }
    
    public class Foo : IFoo
    {
        // you can't declare explicit implemented method as public
        void IFoo.method1() 
        {
        }
    
        public void method2()
        {
        }
    
        private void test()
        {
            var foo = new Foo();
            foo.method1(); //ERROR: not accessible because foo is object instance
            method1(); //ERROR: not accessible because foo is object instance
            foo.method2(); //OK
            method2(); //OK
    
            IFoo ifoo = new Foo();
            ifoo.method1(); //OK, because ifoo declared as interface
            ifoo.method2(); //OK
        }
    }
    
    0 讨论(0)
  • 2021-01-02 06:04

    If a class implements IFoo.Bar explicitly, and a derived class needs IFoo.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-implement IFoo.Bar could call the base-class implementation via ((IFoo)this).Bar(), but if the derived class re-implements IFoo.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 say override 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-implement IFoo.Bar, and since any derived class which doesn't re-implement IFoo.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.

    0 讨论(0)
  • 2021-01-02 06:15

    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.

    0 讨论(0)
提交回复
热议问题