Generics and Interface-Based Programming - Deriving from a Generic Interface
(Page 2 of 4 )
When you derive an interface from a generic interface, you have a number of options as to how to define the sub-interface. Usually, you will prefer to have the sub-interface be a generic interface and provide the sub-interface’s generic type parameters as type parameters to the base interface:
public interface IBaseInterface<T>
{
void SomeMethod(T t);
}
public interface ISubInterface<T> : IBaseInterface<T>
{...}
However, you can also specify a particular type to the base interface, thus making the sub-interface non-generic:
public interface ISubInterface : IBaseInterface<string>
{...}
Typically, when you derive from a generic interface you will do so in a generic subclass and let the client decide on the particular type parameters to use. This is an alternative to defining type-specific subclasses, and it does not limit the subclasses to the use of a particular type parameter:
public class List<T> : IList<T>
{
public void AddHead(T item)
{...}
//Rest of the implementation
}
IList<int> numbers = new List<int>();
IList<string> names = new List<string>();
When a generic class or a generic interface derives from a generic interface, it cannot specify multiple naked generic types to the interface:
//Does not compile:
public class List<T,U> : IList<T>,IList<U>
{...}
Doing so unifies the interfaces when the same type is specified, which violates the uniqueness of interfaces. If that were allowed, the compiler would not know how to resolve a definition such as this:
List<int,int> list;
Explicit Generic Interface Implementation
Just as with regular interfaces, you can implement a generic interface explicitly:
public class NumberList : IList<int>
{
void IList<int>.AddHead(int item)
{...}
void IList<int>.RemoveHead(int item)
{...}
void IList<int>.RemoveAll()
{...}
//Rest of the implementation
}
Note the specification of the type parameter in the explicit implementation:
void IList<int>.AddHead(int item);
This is required because the AddHead() method is not just a method of the generic interface IList<T>; rather, it is a method of the generic interface IList<T> with an integer as a type parameter. The same would be true if the implementing list were itself a generic class:
public class List<T> : IList<T>
{
void IList<T>.AddHead(T item)
{...}
//Rest of the implementation
}
Explicit generic interface implementation is especially handy when the same type implements multiple versions of the generic interface, each with a different concrete type parameter. Although you can use implicit interface implementation, like this:
public class List : IList<int>,IList<string>
{
public void AddHead(int item)
{...}
public void AddHead(string item)
{...}
public void RemoveAll()
{...}
//Rest of the implementation
}
it is preferable in such cases to use explicit interface implementation. The reason is that in methods such asRemoveAll(), you channel the implementation of bothIList<int>andIList<string>to the same method. The client can use eitherIList<int>orIList<string>:
IList<int> list = new List();
list.RemoveAll();
Yet you have no way of knowing in the implementation ofRemoveAll()which internal data structure you should clear when the client calls it. In addition, when you implement the same generic interface multiple times with different type parameters, you often have to use explicit implementation when the compiler cannot resolve the ambiguity. For example, ifIList<T> has a method calledGetHead(), defined as:
public interface IList<T>
{
void AddHead(T item);
void RemoveHead(T item);
void RemoveAll();
T GetHead();
}
you must use explicit interface implementation, because in C# you cannot overload methods only by a different returned type:
public class List : IList<int>,IList<string>
{
int IList<int>.GetHead()
{...}
string IList<string>.GetHead()
{...}
//Rest of the implementation
}
Next: Generic Interfaces as Operators >>
More .NET Articles
More By O'Reilly Media
|
This article is excerpted from chapter three of Programming .NET Components, Second Edition, written by Juval Lowy (O'Reilly, 2006; ISBN: 0596007620). Check it out today at your favorite bookstore. Buy this book now.
|
|