0

While creating a generic interface, I can define constraint that the generic parameter should inherit from a particular interface(IBase).

interface IGeneric<T> where T : IBase
{
    List<T> property{get; set;}
}

Is there any use of this? As I can just substitute this with the following interface, which will serve the same purpose and is much simpler.

interface IGeneric
{
    List<IBase> property{get; set;}
}

It seems to me that we do not need generic at all in this scenario, as we already know that T will be IBase. And the IBase property can already acomodate all its derived types. So what is the use of generic with a specific interface constraint?

V K
  • 1,645
  • 3
  • 26
  • 57

1 Answers1

3

The two interfaces are very different, because List<T> and List<IBase> are very different. Let's suppose there is a class A that implements IBase. This, for one, does not compile:

IGeneric noTypeParameter = ...
noTypeParameter.property = new List<A>();

But this does:

IGeneric<A> hasTypeParameter = ...
noTypeParameter.property = new List<A>();

This is because List is not covariant on T. In fact it is invariant. See also: Convert List<DerivedClass> to List<BaseClass>

If you use IEnumerable<T> and IEnumerable<IBase> , then both of the above code snippets will compile, but the two IGeneric interfaces are still different, because:

IGeneric noTypeParameter = ...
IEnumerable<A> enumerable = noTypeParameter.property; // does not compile


IGeneric<A> hasTypeParameter = ...
IEnumerable<A> enumerable = noTypeParameter.property; //does compile

So basically, with the generic parameter, you are able to pass specific types of List to the interface, and get specific types of List out. However, you can't "store a property of any IBase implementation". Without a type parameter, you are able to store a property of any IBase implementation, but you can't get specific types out of/into IGeneric.

Sweeper
  • 213,210
  • 22
  • 193
  • 313