1

I am trying to cast List into IList, but unable to cast. Compiler allow me to cast it only into IEnumerable:

//Not allowed, why?
public override IList<ILineEntity> Lines
{
   get { return _PharamaLines ?? (_PharamaLines = new List<PharamaLine>()); }
}

//Allowed
public override IEnumerable<ILineEntity> Lines
{
   get { return _PharamaLines ?? (_PharamaLines = new List<PharamaLine>()); }
}

PharamaLine is of type ILineEntity.

Error: Cannot implicitly convert type 'System.Collections.Generic.List<FW.PharamaLine>' to 'System.Collections.Generic.IList<Foundation.Interfaces.ILineEntity>'. An explicit conversion exists (are you missing a cast?)

Ankush Madankar
  • 3,689
  • 4
  • 40
  • 74

1 Answers1

8

The reason is:

IList<T> is invariant, while IEnumerable<out T> is covariant (the out keyword).

If you define a List<PharamaLine>, you basically state that you can only add PharmaLine objects to the list, but you could add different ILineEntity objects to a IList<ILineEntity>, and that would break the contract.

Suppose you have some class OtherLine : ILineEntity. Imagine this code were valid:

var list = new List<PharmaLine>();
var list2 = (IList<ILineEntity>)list; // Invalid!
list2.Add(new OtherLine()); // This should work if the cast were valid

This works for an enumerable, since a sequence of PharmaLine is always a valid sequence of ILineEntity (covariance).

Note that you can also use a IReadOnlyList<out T> which is also covariant but lacks the methods that let you modify the list.

Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158