If you use an interface, the class always strictly implements the interface

The best way to ask this question would be the following example: What are the pros and cons of the two approaches? Is it always better than the other or in certain circumstances? If you use Approach1, will the use of the interface be correct? so how can anyone access public methods?

public interface IDoSomething { void Method1(string operation, User user, string category) void Method2(string operation, User user) void Method3(string operation) } //Approach1 Class A: IDoSomething { public void Method1(string operation, User user, string category) { //do some db logic here... } public void Method2(string operation, User user) { Method1(operation, user, "General"); } public void Method3(string operation) { Method1(operation, User.GetDefaultUser(), "General"); } } 

OR

 //Approach2 Class A: IDoSomething { void IDoSomething.Method1(string operation, User user, string category) { //do some logic here... } void IDoSomething.Method2(string operation, User user) { (this as IDoSomething).Method1(operation, user, "General"); } void IDoSomething.Method3(string operation) { (this as IDoSomething).Method1(operation, User.GetDefaultUser(), "General"); } } 
+6
design c # design-patterns class
source share
4 answers

The phrase you are looking to describe the second approach is an explicit implementation of the interface. Personally, I would not use it most of the time. It’s useful that you need to implement different interfaces with the same member signature in different ways or if you want to limit some members to only visible when working with an expression such as an interface ... but it can be painful if for regardless of the reason why Your caller has a specific type and needs to call some methods specific to a particular type and some interface methods. You can’t even see explicitly implemented methods in one class without clicking this on the interface type.

An explicit interface implementation also means that you cannot override interface methods β€” you will have to override the interface in any subclasses. It basically ends up with a rather difficult task, so I could avoid it if possible.

One final note: an explicit interface implementation also works poorly with dynamic in C # 4 .

+7
source share

Approach 1 is a natural way to implement interfaces in C #. If you are writing a library, your clients expect it; if you use this class yourself, you will save a lot of casting when calling methods.

Use approach 2 ( explicit implementation of the interface ) if you have good reason for this. Good reasons may include

  • implementation of several interfaces sharing the same method signature (but requiring different implementations),
  • which make sense for the interface, but can be misleading for your class.
+2
source share

This is (to some extent) a matter of taste. The main difference is that if you are performing an explicit implementation, these methods cannot be called unless you transfer the object to an interface type:

 A item = new A(); item.Method2(operation, user); // will not compile (item As IDoSomething).Method2(operation, user); // works well 

This approach is useful if you do not want the interface implementations to clutter the list of members in IntelliSense for any reason.

Personally, I tend to use an implicit approach if there is no particular reason to β€œhide” an interface implementation.

0
source share

One very common combination of the two is to implement IEnumerable<T> . Since IEnumerable<T> inherits from IEnumerable , then you must implement both IEnumerable<T>.GetEnumerator() and IEnumerable.GetEnumerator() . Since they have a different type of return value, but the corresponding parameter list (empty), only one maximum can be implicitly implemented.

The most common example is the implementation of the general version:

 public IEnumerator<T> GetEnumerator() { //some code that returns an appropriate object. } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator();//return the result of the other call. } 

Now there is no need to have an implicit one, or you can (with a little casting in an explicit implementation) have it the other way around. However, this is convenient for the following reasons:

  • We would probably prefer the implicit version to be invoked, since it would probably have better type safety and possibly better efficiency if the enumerator object is processed through a more explicit interface.
  • The implicit version will serve both the calling code that wants IEnumerator<T> and the calling code that wants IEnumerator (like an implicit translation), and therefore is most useful.

Now this is one of them, we are forced to use an explicit interface. For an example case, we could choose to think about writing a read-only list that wraps List<T> and implements IList<T> .

All we need to do is delegate the read operations to the wrapped list and drop the unsupported write operations, for example:

 public T this[int idx] { get { return _inner[idx]; } set { throw new NotSupportedException("Read only list."); } } public int Count { get { return _inner.Count; } } public void Add(T item) { throw new NotSupportedException("Read only list."); } public bool IsReadOnly { get { return false; } } 

And so on. However, this is not very useful for people using an object of a particular type, we have a whole group of members that return the same result ( IsReadOnly ) or always throw an exception. Although code using a class through its interface should be able to call these methods and properties, there is no value in this particular class. Therefore, we can do the following:

 public T this[int idx] { get { return _inner[idx]; } } T IList<T>.this[int index] { get { return this[index]; } set { throw new NotSupportedException("Collection is read-only."); } } public int Count { get { return _inner.Count; } } void ICollection<T>.Add(T item) { throw new NotSupportedException("Read only list."); } bool ICollection<T>.IsReadOnly { get { return false; } } 

Now that we fully implement IList<T> , we also offer a much cleaner and more useful interface (in a general sense, rather than a specific "interface" in C #) to users of a particular class.

Please note that this happens for the very reason that it usually makes sense to be implicit: we made all these members more inconvenient for the user of a particular class (for example, the code would have to be translated to IList<T> first). This is good here, since the only result of such awkward code is pointless or dangerous, and making bad ideas harder is good. If such awkwardness simply interfered, that would be a different matter.

0
source share

All Articles