8

Say you have access to a base class 'MyClass' that implements 'IFoo'. 'IFoo' defines the function 'int FooValue()' and 'MyClass' implements it explicitly. Now say you have a subclass of 'MyClass' called 'MySubClass' and you want to override 'FooValue' in that subclass, but you also want the subclass's implementation to be based on the result from the base class's implementation.

Now normally, this would be solved by simply moving the implementation to a protected function in the base class which we'd then simply overide in the subclass. Done and done. But we don't have access to the source code of the base class. We only have it as a reference to a library. So how do you solve this?

Not a Duplicate (update: ...as this one)!

There's this SO question here... C#: Property overriding by specifying the interface explicitly... that shows while you can't override a base class's interface through the normal channels per se, you can explicitly re-implement the same interface on a subclass and that behaves like you're overriding the interface (but in actuality you're re-implementing it, not overriding it.) That said, what I'm trying to figure out is how do I get at the base class's implementation. (That's why IMHO this isn't a duplicate of that question.)

Here's some pseudocode of the base class which again, we don't have access to code-wise...

public interface IFoo
{
    int FooValue();
}

public class MyClass : IFoo
{
    int IFoo.FooValue() <-- Explicit implementation requiring a cast to access.
    {
        return 4;
    }
}

This is what we're trying to do, but obviously this isn't allowed because you can't use 'base' like this.

public class MySubClass : MyClass
{
    int IFoo.FooValue()
    {
        int baseResult = ((IFoo)base).FooValue(); <-- Can't use 'base' like this
        return baseResult * 2;
    }
}

So is this possible?

Community
  • 1
  • 1
Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286
  • 2
    possible duplicate of [How to call an explicitly implemented interface-method on the base class](http://stackoverflow.com/questions/5976216/how-to-call-an-explicitly-implemented-interface-method-on-the-base-class) – Adam Maras Jul 25 '13 at 05:37
  • 1
    I swear... I search and search, and I even go through all of the 'Hey... you may be asking the same as...' questions that get shown when you type your title and I don't find anything similar, but it amazes me that *bang*... right there is the exact same question that I'm asking and mine gets marked as a dup! WTF couldn't I find it? I really searched, I swear!! Every d*@$# time! LOL! – Mark A. Donohoe Jul 25 '13 at 05:59
  • I'm not sure whether it is possible using some "honest" ways, but you can always use reflection to get to and execute whatever private method you want ;) – Artem Tokmakov Jul 25 '13 at 06:02

2 Answers2

3

I will be honest, there is no straightforward answer to this. Feels like a limitation of the language. May be there is some sound reason for the lack of it.

However, I can think of some not so clean work arounds.

  1. Reflection. Imho, the simplest option here. One of those rare cases where reflection is really needed.

  2. Your own interface and base class derived from referenced library.

    //your interface
    public interface IRealFoo : IFoo
    {
        new int FooValue();
    }
    
    //your base class
    public class MyRealClass : MyClass, IRealFoo
    {
        protected virtual int FooValue()
        {
            return ((IFoo)this).FooValue();
        }
    
        int IRealFoo.FooValue()
        {
            return FooValue();
        }
    }
    
    //your child class
    public class MyRealSubClass : MyRealClass
    {
        protected override int FooValue()
        {
            return base.FooValue() * 2;
        }
    }
    

    And you deal with IRealFoo, MyRealClass and so on instead of IFoo, MyClass etc.

    IRealFoo x = new MyRealClass();
    IRealFoo y = new MyRealSubClass();
    Console.WriteLine(x.FooValue()); //4
    Console.WriteLine(y.FooValue()); //8
    
  3. Same as above but abstract class instead of interface.

    Same as above, but you can also have an abstract base class RealFoo instead of interface IFoo. This I think is slightly easier code, but need not be good code. It completely changes the intent of the code.

    public abstract class RealFoo : MyClass
    {
        public virtual int FooValue()
        {
            return ((IFoo)this).FooValue();
        }
    }
    
    public class MyRealClass : RealFoo 
    {
        public override int FooValue() 
        {
            return base.FooValue();
        }
    }
    
    public class MyRealSubClass : MyRealClass 
    {
        public override int FooValue() 
        {
            return base.FooValue() * 2;
        }
    }
    
    //call it like:
    RealFoo x = new MyRealClass();
    RealFoo y = new MyRealSubClass();
    Console.WriteLine(x.FooValue()); //4
    Console.WriteLine(y.FooValue()); //8
    
  4. Extension method along with dynamic.

    public class MyRealClass : MyClass 
    {
        public virtual int FooValue() 
        {
            return ((IFoo)this).FooValue();
        }
    }
    
    public class MyRealSubClass : MyRealClass 
    {
        public override int FooValue() 
        {
            return base.FooValue() * 2;
        }
    }
    
    public static int RealFooValue(this IFoo foo) 
    {
        return ((dynamic)foo).FooValue();
    }
    

    In this one case you can stick with familiar IFoo interface, but you got to call the extension method RealFooValue instead of FooValue. This will be confusing with potentially wrong result when calling FooValue. I dont advise it.

    IFoo x = new MyRealClass();
    IFoo y = new MyRealSubClass();
    Console.WriteLine(x.RealFooValue()); //4
    Console.WriteLine(y.RealFooValue()); //8
    
  5. Switch on type with if-else logic.

    public class MySubClass : MyClass
    {
    
    }
    
    public static int RealFooValue(this IFoo foo) 
    {
        var type = foo.GetType();
    
        if (type == typeof(MyClass))
            return foo.FooValue();
        else if (type == typeof(MySubClass))
            return foo.FooValue() * 2; //logic goes here
    
        throw new Exception();
    }
    

    This has the same problem as above. Dont recommend it.

    IFoo x = new MyClass();
    IFoo y = new MySubClass();
    Console.WriteLine(x.RealFooValue()); //4
    Console.WriteLine(y.RealFooValue()); //8
    
nawfal
  • 70,104
  • 56
  • 326
  • 368
  • This isn't exactly what I wanted. You removed the IFoo from the function name meaning this won't work when casting to an object. I want to be able to cast the subclass to the interface, then call an overrided version of the interface member while still utilizing the base class's functionality. In short, I don't think it's possible. – Mark A. Donohoe Sep 04 '14 at 14:50
  • upvote for providing alternatives, still, keep in mind, the problem here is the language itself – Kjellski Oct 29 '14 at 10:23
  • 1
    @Kjellski true. **My alternative 2 is the best according to me. In fact it is the right way to in scenarios like this.** – nawfal Oct 29 '14 at 12:47
  • 1
    @nawfal I think so too! I found this when I stumbled over the ServiceHostBase to host WCF services on your own. What really bugs me is that once a base class has explicitly implemented the interface, in that case, the IDisposable, you're completely hopeless to call the base in your own dispose, which leads you to not implement a Dispose on your own at all... this is a gold mine for understanding why: http://www.pluralsight.com/courses/idisposable-best-practices-csharp-developers – Kjellski Oct 29 '14 at 20:32
0

Explicit interface realization means that IFoo.FooValue() is private (you can check it by means of reflection):

  MethodInfo mi = typeof(MyClass).GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).Where(m => m.Name.EndsWith("IFoo.FooValue")).ToList()[0];

  if (mi.IsPrivate) {
    // And it is private.... 
  } 

and so you can't call the inherited IFoo.FooValue().

Possible byway

  public interface IFoo
  {
      int FooValue();
  }

  public class MyClass : IFoo
  {
      // This (main logic) should be inherited/override 
      protected virtual int CoreFooValue() 
      {
          return 4;
      }

      // Just a non-virtual interface method which is immutable
      int IFoo.FooValue() 
      {
          return CoreFooValue();
      }
  }

  public class MySubClass : MyClass {
      // Logic is changed, interface is not 
      protected override int CoreFooValue() 
      {
          return base.CoreFooValue() * 2;
      }
  }

See also Non-virtual interface pattern

http://en.wikipedia.org/wiki/Non-virtual_interface_pattern

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • Thanks, but in my question, I already called out not only that solution (2nd paragraph), but why we can't use that here. Specifically we don't have access to the source of MyClass so there's no way we can implement 'CoreFooValue'. – Mark A. Donohoe Jul 25 '13 at 07:21