124

So, what exactly is a good use case for implementing an interface explicitly?

Is it only so that people using the class don't have to look at all those methods/properties in intellisense?

gdoron
  • 147,333
  • 58
  • 291
  • 367
Master Morality
  • 5,837
  • 6
  • 31
  • 43

11 Answers11

149

If you implement two interfaces, both with the same method and different implementations, then you have to implement explicitly.

public interface IDoItFast
{
    void Go();
}
public interface IDoItSlow
{
    void Go();
}
public class JustDoIt : IDoItFast, IDoItSlow
{
    void IDoItFast.Go()
    {
    }

    void IDoItSlow.Go()
    {
    }
}
Iain
  • 10,814
  • 3
  • 36
  • 31
  • Yes exactly this is one case that EIMI solves. And other points are covered by "Michael B" answer. – crypted Nov 05 '10 at 04:20
  • 10
    Excellent example. Love the interface/class names! :-) – Brian Rogers Oct 17 '13 at 00:18
  • 11
    I don't love it, two methods with the same signature in a class that do very different things? This is extremely dangerous stuff and is very likely going to cause havoc in any large development. If you have code like this I'd say your analysis and design is up the wahzoo. – Mick Apr 28 '15 at 02:32
  • 4
    @Mike The interfaces might belong to some API or to two different APIs. Maybe *love* is a bit exaggerated here but I'd at least be glad that explicit implementation is available. – TobiMcNamobi May 06 '15 at 12:00
  • @BrianRogers And the method names too ;-) – Sнаđошƒаӽ Aug 07 '16 at 07:04
67

It's useful to hide the non-preferred member. For instance, if you implement both IComparable<T> and IComparable it is usually nicer to hide the IComparable overload to not give people the impression that you can compare objects of different types. Similarly, some interfaces are not CLS-compliant, like IConvertible, so if you don't explicitly implement the interface, end users of languages that require CLS compliance cannot use your object. (Which would be very disastrous if the BCL implementers did not hide the IConvertible members of the primitives :))

Another interesting note is that normally using such a construct means that struct that explicitly implement an interface can only invoke them by boxing to the interface type. You can get around this by using generic constraints::

void SomeMethod<T>(T obj) where T:IConvertible

Will not box an int when you pass one to it.

Michael B
  • 7,512
  • 3
  • 31
  • 57
  • 1
    You have a typo in your constraint. To clerify, the code above does work. It needs to be in the initial declaration of the method signature in the Interface. The original post did not specify this. Also, the proper format is "void SomeMehtod(T obj) where T:IConvertible. Note, there is an extra colon between ")" and "where" that should not be there. still, +1 for clever use of generics to avoid expensive boxing. – Zack Jannsen Sep 04 '12 at 16:31
  • 1
    Hi Michael B. So why in implementation of string in .NET there public implementation of IComparable: public int CompareTo(Object value) { if (value == null) { return 1; } if (!(value is String)) { throw new ArgumentException(Environment.GetResourceString("Arg_MustBeString")); } return String.Compare(this,(String)value, StringComparison.CurrentCulture); } Thanks! – zzfima Jun 30 '15 at 13:02
  • `string` was around around before generics and this practice was in vogue. When .net 2 came around they didn't want to break the public interface of the `string` so they left it around as it was with the safeguard in place. – Michael B Jun 30 '15 at 14:00
  • @MichaelB hi, could you explain a little bit more why end users of languages that require CLS compliance cannot use your object if you don't explicitly implement the interface like like IConvertible –  Feb 20 '21 at 01:22
  • @MichaelB the msdn doc says : The common language runtime typically exposes the IConvertible interface through the Convert class. The common language runtime also uses the IConvertible interface internally, in explicit interface implementations, to simplify the code used to support conversions in the Convert class and basic common language runtime types." but I 'm not sure how it can simplify the code used to support conversions in the Convert class. –  Feb 20 '21 at 01:23
36

Some additional reasons to implement an interface explicitly:

backwards compatibility: In case the ICloneable interface changes, implementing method class members don't have to change their method signatures.

cleaner code: there will be a compiler error if the Clone method is removed from ICloneable, however if you implement the method implicitly you can end up with unused 'orphaned' public methods

strong typing: To illustrate supercat's story with an example, this would be my preferred sample code, implementing ICloneable explicitly allows Clone() to be strongly typed when you call it directly as a MyObject instance member:

public class MyObject : ICloneable
{
  public MyObject Clone()
  {
    // my cloning logic;  
  }

  object ICloneable.Clone()
  {
    return this.Clone();
  }
}
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Wiebe Tijsma
  • 10,173
  • 5
  • 52
  • 68
  • For that one, I'd I'd prefer `interface ICloneable { T Clone(); T self {get;} }`. Note that there is deliberately no `ICloneable` constraint on T. While an object can generally only be safely cloned if its base can be, one may wish to derive from a base class which could be safely cloned an object of a class that can't. To allow for that, I'd recommend against having inheritable classes expose a public clone method. Instead have inheritable classes with a `protected` cloning method and sealed classes which derive from them and expose public cloning. – supercat May 14 '13 at 22:37
  • Sure that would be nicer, except there's no covariant version of ICloneable in the BCL, so you'd have to create one right? – Wiebe Tijsma May 15 '13 at 08:30
  • All 3 examples depend on unlikely situations and break interfaces best practices. –  Sep 10 '18 at 23:09
13

Another useful technique is to have a function's public implementation of a method return a value which is more specific than specified in an interface.

For example, an object can implement ICloneable, but still have its publicly-visible Clone method return its own type.

Likewise, an IAutomobileFactory might have a Manufacture method which returns an Automobile, but a FordExplorerFactory, which implements IAutomobileFactory, might have its Manufacture method return a FordExplorer (which derives from Automobile). Code which knows that it has a FordExplorerFactory could use FordExplorer-specific properties on an object returned by a FordExplorerFactory without having to typecast, while code which merely knew that it had some type of IAutomobileFactory would simply deal with its return as an Automobile.

T.S.
  • 18,195
  • 11
  • 58
  • 78
supercat
  • 77,689
  • 9
  • 166
  • 211
  • 3
    +1... this would be my preferred usage of explicit interface implementations, though a small code sample would probably a bit more clear than this story :) – Wiebe Tijsma Aug 16 '11 at 17:05
7

It's also useful when you have two interfaces with the same member name and signature, but want to change the behavior of it depending how it's used. (I don't recommend writing code like this):

interface Cat
{
    string Name {get;}
}

interface Dog
{
    string Name{get;}
}

public class Animal : Cat, Dog
{
    string Cat.Name
    {
        get
        {
            return "Cat";
        }
    }

    string Dog.Name
    {
        get
        {
            return "Dog";
        }
    }
}
static void Main(string[] args)
{
    Animal animal = new Animal();
    Cat cat = animal; //Note the use of the same instance of Animal. All we are doing is picking which interface implementation we want to use.
    Dog dog = animal;
    Console.WriteLine(cat.Name); //Prints Cat
    Console.WriteLine(dog.Name); //Prints Dog
}
vcsjones
  • 138,677
  • 31
  • 291
  • 286
6

It can keep the public interface cleaner to explicitly implement an interface, i.e. your File class might implement IDisposable explicitly and provide a public method Close() which might make more sense to a consumer than Dispose().

F# only offers explicit interface implementation so you always have to cast to the particular interface to access its functionality, which makes for a very explicit (no pun intended) use of the interface.

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
  • I think that most versions of VB also only supported explicit interface definitions. – Gabe Nov 05 '10 at 03:47
  • 1
    @Gabe - it's more subtle than that for VB - the naming and accessibility of members that implement an interface are separate from indicating that they're part of the implementation. So in VB, and looking at @Iain's answer (current top answer), you could implement IDoItFast and IDoItSlow with public members "GoFast" and "GoSlow", respectively. – Damien_The_Unbeliever Nov 05 '10 at 07:36
  • 2
    I don't like your particular example (IMHO, the only things that should hide `Dispose` are those which will never require cleanup); a better example would be something like an immutable collection's implementation of `IList.Add`. – supercat Oct 23 '13 at 19:57
  • "You always have to cast to the particular interface to access its functionality". I don't see why: as long as you program to an interface, not to implementation, the client using your object needn't know which particular implementation it received, and needn't cast it, but just consume it in terms of interface. – Arialdo Martini Dec 06 '20 at 08:26
5

Another reason for explicit implementation is for maintainability.

When a class gets "busy"--yes it happens, we don't all have the luxury of refactoring other team members' code--then having an explicit implementation makes it clear that a method is in there to satisfy an interface contract.

So it improves the code's "readability".

h bob
  • 3,610
  • 3
  • 35
  • 51
  • IMHO it is more important to decide whether the class should or should not be exposing the method to its clients. That drives whether to be explicit or implicit. To document that several methods belong together, in this case because they satisfy a contract - thats what `#region` is for, with an appropriate title string. And a comment on the method. – ToolmakerSteve Jan 16 '17 at 16:50
5

If you have an internal interface and you don't want to implement the members on your class publicly, you would implement them explicitly. Implicit implementations are required to be public.

Mike Dour
  • 3,616
  • 2
  • 22
  • 24
2

A different example is given by System.Collections.Immutable, in which the authors opted to use the technique to preserve a familiar API for collection types while scraping away the parts of the interface that carry no meaning for their new types.

Concretely, ImmutableList<T> implements IList<T> and thus ICollection<T> (in order to allow ImmutableList<T> to be used more easily with legacy code), yet void ICollection<T>.Add(T item) makes no sense for an ImmutableList<T>: since adding an element to an immutable list must not change the existing list, ImmutableList<T> also derives from IImmutableList<T> whose IImmutableList<T> Add(T item) can be used for immutable lists.

Thus in the case of Add, the implementations in ImmutableList<T> end up looking as follows:

public ImmutableList<T> Add(T item)
{
    // Create a new list with the added item
}

IImmutableList<T> IImmutableList<T>.Add(T value) => this.Add(value);

void ICollection<T>.Add(T item) => throw new NotSupportedException();

int IList.Add(object value) => throw new NotSupportedException();
fuglede
  • 17,388
  • 2
  • 54
  • 99
0

This is how we can create Explicit Interface: If we have 2 interface and both the interface have the same method and a single class inherit these 2 interfaces so when we call one interface method the compiler got confused which method to be called, so we can manage this problem using Explicit Interface. Here is one example i have given below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace oops3
{
    interface I5
    {
        void getdata();    
    }
    interface I6
    {
        void getdata();    
    }

    class MyClass:I5,I6
    {
        void I5.getdata()
        {
           Console.WriteLine("I5 getdata called");
        }
        void I6.getdata()
        {
            Console.WriteLine("I6 getdata called");
        }
        static void Main(string[] args)
        {
            MyClass obj = new MyClass();
            ((I5)obj).getdata();                     

            Console.ReadLine();    
        }
    }
}
samus
  • 6,102
  • 6
  • 31
  • 69
Debendra Dash
  • 5,334
  • 46
  • 38
0

In case of explicitly defined interfaces, all methods are automatically private, you can't give access modifier public to them. Suppose:

interface Iphone{

   void Money();

}

interface Ipen{

   void Price();
}


class Demo : Iphone, Ipen{

  void Iphone.Money(){    //it is private you can't give public               

      Console.WriteLine("You have no money");
  }

  void Ipen.Price(){    //it is private you can't give public

      Console.WriteLine("You have to paid 3$");
  }

}


// So you have to cast to call the method


    class Program
    {
        static void Main(string[] args)
        {
            Demo d = new Demo();

            Iphone i1 = (Iphone)d;

            i1.Money();

            ((Ipen)i1).Price();

            Console.ReadKey();
        }
    }

  // You can't call methods by direct class object
Simon Bosley
  • 1,114
  • 3
  • 18
  • 41
Md Shahriar
  • 2,072
  • 22
  • 11
  • 1
    "all methods are automatically private" - this isn't technically correct, b/c if they were in fact private then they wouldn't be callable at all, casting or not. – samus Jun 16 '17 at 14:03