What’s the difference between these two, and what is the “correct” one?
public interface IMessage
{
/// <summary>
/// Array used to hold all bytes that will be written.
/// </summary>
IList Buffer { get; set; }
}
and
public interface IMessage<T> where T : IList
{
/// <summary>
/// Array used to hold all bytes that will be written.
/// </summary>
T Buffer { get; set; }
}
Edit 1: Fixed – can’t have fields on interfaces. (Thanks BoltClock)
Edit 2: Fixed – can’t have encapsulation on interfaces. (Thanks KeithS)
In the first case, your buffer is defined to be of type IList. It can, at runtime, be assigned any implementation of IList, and any creator of implementations of this interface does not have to know exactly what implementation will be used. However, code cannot know, at runtime, which exact concrete implementation is used, and so at design-time when referring to this property as a member of the interface, you will never have access to any methods not exposed explicitly by the IList interface.
In the second case, you are defining a generic. Wherever this generic definition remains “open” (T is not defined), you are still restricted to using the methods of IList. However, something must close this generic, either an implementation of the interface or the definition of a particular instance of an implementation that keeps the generic open. Once the generic is closed, the exact, concrete type of buffer is known, and methods can be called on it that are not necessarily defined by IList. But, once the generic is closed, an instance or class that defines a particular generic type can’t be given a different implementation of IList to use as the buffer.
So, some examples (assuming that the protected field, which you can’t specify on an interface, is actually a mutable public property):