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() {
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.