Ufuk Hacıoğulları
Ufuk Hacıoğulları

Reputation: 38488

How can a concrete class hide a member of the interface that it implements

I will give an example from .NET.

ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary

Here you can see ConcurrentDictionary implementing dictionary interfaces. However I can't access Add<TKey,TValue> method from a ConcurrentDictionary instance. How is this possible?

IDictionary<int, int> dictionary = new ConcurrentDictionary<int, int>();
dictionary.Add(3, 3); //no errors

ConcurrentDictionary<int, int> concurrentDictionary = new ConcurrentDictionary<int, int>();
concurrentDictionary.Add(3, 3); //Cannot access private method here

Update:

I know how I can access it but I didn't know explicitly implementing an interface could allow changing access modifiers to internal. It still doesn't allow making it private though. Is this correct? A more detailed explanation about that part would be helpful. Also I would like to know some valid use cases please.

Upvotes: 6

Views: 915

Answers (7)

Ufuk Hacıoğulları
Ufuk Hacıoğulları

Reputation: 38488

Thanks everbody for great answers, one of the deleted answers confused me about the access modifiers. I was able to find some nice explanations from the linked questions.

Implicit and Explicit Interface Implementations by Michael Hopcroft

Some use cases by Jon Skeet

Implementing IDisposable explicitly

Design Guidelines for Explicit Member Implementation by Brad Abrams

Odious ambiguous overloads, part one & part two by Eric Lippert

Upvotes: 0

yoozer8
yoozer8

Reputation: 7489

The access modifier has not been changed; ConcurrentDictionary<TKey, TValue> has defined the method IDictionary.Add through explicit interface implementation, and has not implemented an Add method.

If you look at the class documentation, you will see that no Add method exists (so concurrentDictionary.Add(3, 3); would be analogous to calling concurrentDictionary.MethodThatDoesntExist(3, 3);). However, under the Explicit Interface Implementations section, you can see that there are methods ICollection.Add and IDictionary.Add.

This feature allows a class to implement multiple interfaces that share a method name without requiring the implementation to be the same for each interface.

Upvotes: 0

Oded
Oded

Reputation: 499302

It is implemented as an explicit interface implementation, meaning you need a variable of the IDictionary<TKey, TValue> type to access it.

See the documentation of ConcurrentDictionary<TKey, TValue>, under the Explicit Interface Implementations section.

If you cast the concurrent dictionary to IDictionary<TKey, TValue>, you will be able to call Add on it.


I didn't know explicitly implementing an interface could allow changing access modifiers to internal. It still doesn't allow making it private though. Is this correct?

No, this is not correct.

Explicit interface implementations do not change the access modifiers. They change how you can access the members that were implemented that way (i.e. require you to use a variable of the interface type). They are still public members, but can only be accessed using the interface type, not the implementing type.

Upvotes: 4

stuartd
stuartd

Reputation: 73303

Because the IDictionary.Add method is explicitly implemented by ConcurrentDictionary.

To access it from the class without having to declare the variable as IDictionary, cast it to the required interface:

((IDictionary)concurrentDictionary).Add(3, 3)

Upvotes: 7

MattDavey
MattDavey

Reputation: 9027

This is done through explicit interface implementation

public interface ISomeInterface
{
    void SomeMethod();
}

public class SomeClass : ISomeInterface
{
    void SomeInterface.SomeMethod()
    {
        // ...
    }
}

Now when you have a reference to a SomeClass object, you will not see the SomeMethod method available. In order to call it you would have to cast the object back to ISomeInterface...

((ISomeInterface)mySomeClass).SomeMethod();

This is one of the more under-utilizied useful features of C# imo

Upvotes: 5

daryal
daryal

Reputation: 14929

the interface is implemented explicitly. you can not access to Add method using an instance of A class in the following example.

public interface IA
{
    void Add();
}

public class A : IA
{
    void IA.Add()
    {
        throw new NotImplementedException();
    }
}

Upvotes: 2

Marc Gravell
Marc Gravell

Reputation: 1064004

Explicit interface implementation. For a simpler example:

public interface IFoo {
    void Bar();
}
public class Foo : IFoo {
    void IFoo.Bar() { ... }
}

here Bar is not on the public API of Foo.

Upvotes: 2

Related Questions