Reputation: 38488
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
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
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
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
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
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
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
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