21

What is the proper way to override explicit implementations of an interface in a child class?

public interface ITest
{
    string Speak();
}

public class ParentTest : ITest
{
    string ITest.Speak()
    {
        return "Meow";
    }
}

public class ChildTest : ParentTest
{
    // causes compile time errors
    override string ITest.Speak()
    {
        // Note: I'd also like to be able to call the base implementation
        return "Mooo" + base.Speak();
    }
}

The above is a best guess for the syntax, but obviously it's wrong. It causes the following compile time errors:

error CS0621:

`ChildTest.ITest.Speak()': virtual or abstract members cannot be private

error CS0540:

ChildTest.ITest.Speak()': containing type does not implement interfaceITest'

error CS0106:

The modifier `override' is not valid for this item

I can actually get this to work without using explicit interfaces so it's not actually blocking me but I would really like know, for my own curiosity, what is the correct syntax if wanted to do this with explicit interfaces?

James McMahon
  • 48,506
  • 64
  • 207
  • 283
  • 2
    What's wrong with implicit interface implementation? What are you trying to accomplish? – chomba May 18 '16 at 22:23
  • @chomba, The use of explicit interfaces has been a style choice in my codebase. I just think it's a lot cleaner to look at a class that implements 4 or 5 different interfaces and know what methods are associated with what interface. It's been fine for the majority of my use cases, this is the first time I've run into a limitation with them. – James McMahon May 18 '16 at 22:27
  • @JamesMcMahon As far as I know the main use case for explicit is multiple interfaces with members with identical signatures. I very rarely see them used and if I did I'd feel like whoever wrote the code didn't write C# very often. – Casey May 18 '16 at 22:28
  • Yeah that gets into programmer preference, there is a bunch of answers at http://stackoverflow.com/questions/143405/ that go into the pros / cons of each approach. – James McMahon May 18 '16 at 22:32
  • @JamesMcMahon Yes, I agree, but I feel like this is one of those things that's mostly agreed upon by people who use the language often. It's the same way I'd feel weird about seeing C# code that said `var some_object = new my_class()`; there's nothing wrong with snake case but it feels out of place in C#. – Casey May 18 '16 at 23:50

5 Answers5

20

An explicit interface implementation cannot be a virtual member. See section 13.4.1 of the C# language specification (it is outdated but this logic does not appear to have changed in C# 6.0). Specifically:

It is a compile-time error for an explicit interface member implementation to include access modifiers, and it is a compile-time error to include the modifiers abstract, virtual, override, or static.

This means, you will never be able to directly override this member.

What you can do as a workaround is to call another virtual method from your explicit implementation:

class Base : IBla
{
    void IBla.DoSomething()
    {
        this.DoSomethingForIBla();
    }

    protected virtual void DoSomethingForIBla()
    {
        ...
    }
}

class Derived : Base
{
    protected override void DoSomethingForIBla()
    {
        ...
    }
}
Bas
  • 26,772
  • 8
  • 53
  • 86
  • 1
    Great answer with the link to the docs. I've been using explicit interface as a stylistic choice without realize they had that limitation. – James McMahon May 18 '16 at 22:22
  • Awesome answer @Bas! I've been cracking my head on the wall trying to figure out why I wasn't being able of overriding my interface implementations. Thanks! – João Ignacio Jul 08 '20 at 18:00
15

I also had a situation where I thought I wanted to override an explicit interface implementation and call the base class and found this question with its answers saying "can't be done".

The first thing to note is that in order to override the explicit interface implementation WITHOUT calling the base class is fairly simple. The derived class merely needs to implement the interface itself.

public class ChildTest : ParentTest, ITest
{
  string ITest.Speak()
  {
    return "Mooo";
  }
  // Note: any other interface functions will call ParentTest's implementation
}

However, there is now no "legitimate" way to call ParentTest's implementation of ITest.Speak on an object of type ChildTest, as any attempt to use the interface will result in ChildTest's implementation being called instead.

Thus, it is only the call to the base implementation that causes complication. To satisfy my curiosity, I proved that it CAN be done, but really it shouldn't...

Leaving the base class unchanged, the following does in fact allow the base class to be called using reflection.

public class ChildTest : ParentTest, ITest
{
  string ITest.Speak()
  {
    return "Mooo" + typeof(ParentTest).GetMethod("ITest.Speak", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(this, new object[0]) as string;
  }
}

NB if the sample code is enclosed in a namespace, the fully qualified interface name is required. e.g. "MyNamespace.ITest.Speak"

If the function will be called repeatedly and/or for many objects, performance can be improved by caching the method info, and/or creating a delegate for the base call, e.g.:

public class ChildTest : ParentTest, ITest
{
  static ChildTest()
  {
    baseSpeakMethodInfo = typeof(ParentTest).GetMethod("ITest.Speak", BindingFlags.Instance | BindingFlags.NonPublic);
  }

  static private MethodInfo baseSpeakMethodInfo;

  public ChildTest()
  {
    baseSpeak = baseSpeakMethodInfo.CreateDelegate(typeof(Func<string>), this) as Func<string>;
  }

  private Func<string> baseSpeak;

  string ITest.Speak()
  {
    return "Mooo" + baseSpeak();
  }
}

The only advantage this has over other answers is that it works if you cannot modify the base class. Otherwise, it's a horrible solution, and a mechanism should be created in the base class (as in other answers) to provide the derived class with a legitimate way to call the base implementation.

Steve
  • 613
  • 5
  • 15
1

You can use a protected virtual method, and keep the implementation non-public, so you still have explicit interface implementation which is just a wrapper around the implementation:

public class ParentTest : ITest
{
    protected virtual string Speak_Impl()
    {
        return "Meow";
    }
    string ITest.Speak()
    {
        return Speak_Impl();
    }
}

public class ChildTest : ParentTest
{
    protected override string Speak_Impl()
    {
        return "Mooo";
    }
}
Joe Enos
  • 39,478
  • 11
  • 80
  • 136
0

public virtual string Speak() in the parent and public override string Speak() in the child should work fine. You cannot use explicit interfaces for this use case. You can work around it by declaring a protected member and calling it in the explicit interface implementations if you need to use them.

Casey
  • 3,307
  • 1
  • 26
  • 41
  • 2
    That's no longer an explicit interface at that point. If you try and add the virtual keyword in front an explicit interface you get `error CS0106: The modifier `virtual' is not valid for this item` – James McMahon May 18 '16 at 22:12
  • @JamesMcMahon There's no reason your example needs to be an explicit interface; if that's a requirement you should change your example/question. – Casey May 18 '16 at 22:13
  • Updated the question to clarify things – James McMahon May 18 '16 at 22:14
  • @JamesMcMahon Explicit interface is only needed when you have to implement multiple interfaces with methods with the same signatures, and in this case the answer is to create methods that *don't* have those names and call them in the explicit interface implementations – Casey May 18 '16 at 22:15
0

You can't override explicit interface implementations. They cannot be virtual so there's no way to directly override them. You can, however, make them indirectly virtual by having it call a protected virtual member:

public interface ITest
{
    string Speak();
}

public class ParentTest : ITest
{
    string ITest.Speak()
    {
        return Speak();
    }

    protected virtual string Speak()
    {
        return "Meow";
    }

}

public class ChildTest : ParentTest
{
    protected override string Speak()
    {
        return "Mooo";
    }
}
D Stanley
  • 149,601
  • 11
  • 178
  • 240