Every interface explicitly implemented? (IoC invol

2019-07-16 04:57发布

问题:

I'm very aware of the fact that such a question has probably been posted already. Yet with the involvement of IoC in this case and a lot of code I've seen a colleague in a company I'm new in made this question arise.

Scenario:

In the codebase of one product this colleague build every interface is implemented explicitly. The whole application is constructed through structure map, yet in some places the concrete types are used and cast like this

((IInterface)concreteClass).SomeMethod()

Background:

That colleague explained to me, after asking what it is about explicitly implementing all interfaces, that they introduced StructureMap recently and many people would still just use the concrete types. So in essence it's a means to "educate" people in the company.

My cents on the matter:

First of all, the switch to StructureMap has been done several years ago and while this, sort of, forces to use interfaces more, in my opinion this is not the right way. The way I see it, people who know about the concrete type can see the implementation and easily to what I showed above... just cast it. Clear communication or coding conventions would make this much better. If IoC is used and no concrete class, then explicitly implmenting an interface is completely useless.

I've also heard that this can really mess up inheritance, but don't know of an example. I've also seen Jon Skeet sort of discouraging from using it the way mentioned above, but rather the way it was intended to use, like with IEnumerable<> and other name clashes.

Can anyone shed some light on this matter for me. Pros and cons (although I'm highly biased to not doing it, hence my post here) and especially reasons why one or the other.

Thanks!

Edit: I'm very well aware that this is not a matter of right or wrong, nor is there a real answer. This is more of a question to learn to know deficits of each approach. Why would I use in one scenario one over the other approach?

回答1:

There are two main potential advantages to explicit interface implementations:

  1. A single class can implement two interfaces that have conflicting method signatures, and subtly different implementations for each. It is rare for this to happen, and it's typically not a problem to do on-demand rather than by-default.
  2. You can "hide" certain methods that you don't expect people to use except in specific contexts. The Interface Segregation Principle encourages us to not expose methods to consumers that they are unlikely to need.

One good example of #2 being used is the way that Entity Framework contexts avoid exposing their underlying ObjectContext directly (because most people shouldn't be using it in their code), but still make this property available if you cast the context to an IObjectContextAdapter.

In the case of your company, it sounds like they're trying to leverage #2, but for the wrong reasons. They want to hide method implementations, not because the method isn't expected to be used, but because they do expect it to be used--and when it is they're hoping it'll encourage developers to decouple their code from the concrete types. Your code sample indicates that it is missing the mark--developers are still instantiating concrete types and then casting them in order to get access to the interface methods.



回答2:

A good starting point could be this article: Why I use explicit interface implementation as a default implementation technique

Initially I wasn't to inclined on implementing interfaces explicitly but I have to admit the writer makes some very good points.

UPDATE: In comments below, the OP is stating that explicit implementation screws up inheritance as you can not override the interface implementation in a derived type. I'm not sure if I'm undestanding correctly the issue:

public interface IFooable
{
     void Foo();
     void FooAgain();
}

public class Blah: IFooable
{
     void IFooable.Foo()
     {
         Console.WriteLine("Hi from 'Blah'!");
     }

     void IFooable.FooAgain() {}
}

public class Bar: Blah, IFooable
{
     void IFooable.Foo()
     {
         Console.WriteLine("Hi from 'Bar'!");
     }
}

public static void Main()
{
   var fooList = new List<IFooable>();
   fooList.Add(new Blah());
   fooList.Add(new Bar());

   foreach (var fooable in fooList) //Outputs "Hi from 'Blah'!" / "Hi from 'Bar'!"
       fooable.Foo();

   Console.ReadLine();
}