6

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.

Ufuk Hacıoğulları
  • 37,978
  • 12
  • 114
  • 156
  • 2
    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). – Oded Jan 11 '13 at 14:49
  • 1
    See http://stackoverflow.com/questions/6129857/is-the-use-of-explicit-interface-implementation-meant-for-hiding-functionality for some comments on usage – stuartd Jan 11 '13 at 14:50
  • 1
    The default visibility level inside classes is `private` opposed to `package` in java. Explicit interface implementations are private, so no, your assumption is not correct. – Sebastian Graf Jan 11 '13 at 15:15

7 Answers7

7

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)
stuartd
  • 70,509
  • 14
  • 132
  • 163
5

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

MattDavey
  • 8,897
  • 3
  • 31
  • 54
4

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.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
2

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.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
2

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();
    }
}
daryal
  • 14,643
  • 4
  • 38
  • 54
0

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.

yoozer8
  • 7,361
  • 7
  • 58
  • 93
0

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

Community
  • 1
  • 1
Ufuk Hacıoğulları
  • 37,978
  • 12
  • 114
  • 156