In fact, the recommended is the implicit one. There are cases where explicit is necessary. There are controversies whether this is a good thing or not. Some say it shouldn’t even exist in language because it can create confusion. I am always of the opinion that if there is something that can solve a problem better, you should give it that option, even if you have restrictions of use. Misuse is a problem that any resource may have.
Explicit X implicit interface
The implicit is what everyone does all the time, you implement in the class one or more methods that a "command" interface and that this class wants to conform. It’s no secret.
The explicit is the implementation nominally telling which interface this implementation should be used for. It is an exceptional form of implementation because there will be some situation where a behavior different from the normal class is required when waiting for the interface.
Remembering what polymorphism is
In polymorphism you can treat an object of one type as if it were of another type. So if you create a method that takes, for example, a IEnumerable
, any object that implements this interface, can be passed to that method and all it will do is access the GetEnumerator()
(specified by the interface). It will not access other parts of the object, so it does not matter to it the rest it has on the object. All that matters is that it’s there.
The C# compiler ensures the presence of what matters. In most cases the presence of the method in so-called implicit form is sufficient and everything will work.
What good is?
As much as the ideal is to do it one way, there are always situations where things don’t work out the way you want. In addition there is language limitation in making certain patterns that the solution turns out to be the use of the explicit interface. Here are the main reasons to use.
Diamond problem
There are some rare cases where this implementation should be a little different. This occurs more often when there are conflicting implementations of two interfaces. One must work one way and the other must work another way. Normally you could only have the implementation one way. The explanation of the implementation allows for a variation. A common situation occurs in the case of diamond problem. The interface helps solve the problem, but there are cases that can become a bigger problem having the same implementation for more than one interface.
To make explicit the interface name is used before the method name. Example:
public void Paint() { //implícita
WriteLine("Paint method in SampleClass");
}
void IControl.Paint() { //explícita para a IControl
WriteLine("IControl.Paint");
}
void ISurface.Paint() { //explícita para a ISurface
WriteLine("ISurface.Paint");
}
How it performs:
var sc = new SampleClass();
IControl ctrl = (IControl)sc;
ISurface srfc = (ISurface)sc;
sc.Paint(); //Paint method in SampleClass
ctrl.Paint(); //IControl.Paint
srfc.Paint(); //ISurface.Paint
See the effects of calling by class and by each of the interfaces. Note how each call executes a different method even though it is theoretically the same method. It is working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.
Specialization
Another case is that the class implementation can be done more efficiently or do something extra, but this may not conform to what is expected in the interface. So when it is used in a place that is expected to interface, it runs the simplest and most compatible implementation. When you can call the class implementation call the implementation "improved". This improved version could hurt the expectation of what the interface should do.
Compatibility
It can be useful in case of future interface changes, so it will help maintain compatibility with the old and new version, after all the interface now requires something that already existed in its class. This is common in more internal systems, especially when adding a method with an existing name but with a new signature.
An example would be an interface ICalculo
who has a method CalculaSaldo()
, a new method is created CalculaSaldo(TipoCalculo tipo)
. Only that the class that already conformed to this interface had already anticipated this need and created a method with this signature, but the implementation does not match what is expected of this method specified in the interface. The solution is to create a new method explicitly to meet the interface.
That is, it is Gambi, it should never be done this, but there are cases of need and when it happens at least it is a solution.
Encapsulation
It can help improve encapsulation, so you make it clear that implementations are different, even if they are not. In doing so, at least when you need it, you can change one of them without worrying about what will happen to the publicly exposed method. Example:
interface IDisposable {
void Dispose();
}
class MyFile : IDisposable {
void IDisposable.Dispose() {
Close();
}
public void Close() {
// fecha o que tem que fechar aqui
SuppressFinalize(this);
}
}
Public static void Main() {
var file = new MyFile();
file.Dispose(); //erro não pode chamar aqui
IDisposable file2 = new MyFile();
File2.Dispose(); //ok, funciona
}
Thus the call of the method Dispose()
is prevented when called by the class. Which is a good thing, since many programmers make this call by mistake, which is not recommended and they don’t know it.
It is a way to simulate a private implementation of the interface. There are cases where the concrete implementation does not need the interface methods for it itself. It needs only to meet the demand of the interface, so it is better to hide it from the concrete objects generated based on it.
This is a form of explicitly program for the interface and not for implementation.
The best way is always to meet the ISP, and explicit implementation can facilitate or hinder this. Here it depends on the case, not always what we have in hand can be the ideal.
Classes that inherit from their class with explicit implementations do not receive these implementations. Neither can they have them virtual. Only implicit ones are inherited. This is an important thing to observe when thinking about design hierarchy. There are cases where you want this and want to maintain the right level of specialization.
One advantage of using this technique is that if one day the interface removes a method from your contract (rarely happens), the explicit interfaces will generate an error in the compiler and force you to remove them from the code. In the implicit implementation there is no error because it becomes part of the class. In fact, in that case the removal could only be done with great care and risk acceptance.
Can be bad
Besides being able to cause confusion in its use, not everyone understands what will be called and the person may have difficulties even to debug the code.
There is a practical problem of performance loss by being required to do Boxing in types by value, it is recommended to avoid explicit interfaces in these types. Cannot access a type per value from the interface without boxing it in a reference.
Completion
Like everything, it has advantages and disadvantages. Apart from the limitation of language, a good design avoid the use of this mechanism. And it should be avoided even
Eric Lippert’s article on the subject. Part 2.
Guideline by Brad Adams.
As in C# we have the question of being able to have two methods with the same name, for me makes sense the explicit implementation. In languages like PHP, which does not accept methods with equal names for example, it would make no sense at all.,
– Wallace Maxters
@Wallacemaxters one thing has nothing to do with the other. Overloding is unrelated to this. It is even possible for the interface to have more than one full me with the same name (but not the same signature). In fact it is opposite. In PHP it would make even more sense. This mechanism is to disambiguate the implementation of the same method (same signature). Note that technically the name is different, since it has a "surname" in it.
– Maniero