Daniil
Daniil

Reputation: 1398

C# generics and interfaces and simple OO

My C# skills are low, but I can't understand why the following fails:

public interface IQuotable {}
public class Order : IQuotable {}
public class Proxy {
  public void GetQuotes(IList<IQuotable> list) { ... }
}

Then the code is as follows:

List<Order> orders = new List<Orders>();
orders.Add(new Order());
orders.Add(new Order());

Proxy proxy = new Proxy();
proxy.GetQuotes(orders); // produces compile error

Am I simply doing something wrong and not seeing it? Since Order implements Quotable, a list of order would go in as IList of quoatables. I have something like in Java and it works, so I'm pretty sure its my lack of C# knowledge.

Upvotes: 5

Views: 436

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1500475

You can't convert from a List<Order> to an IList<IQuotable>. They're just not compatible. After all, you can add any kind of IQuotable to an IList<IQuotable> - but you can only add an Order (or subtype) to a List<Order>.

Three options:

  • If you're using .NET 4 or higher, you can use covariance if you change your proxy method to:

    public void GetQuotes(IEnumerable<IQuotable> list)
    

    This only work if you only need to iterate over the list, of course.

  • You could make GetQuotes generic with a constraint:

    public void GetQuotes<T>(IList<T> list) where T : IQuotable
    
  • You could build a List<IQuotable> to start with:

    List<IQuotable> orders = new List<IQuotable>();
    orders.Add(new Order());
    orders.Add(new Order());
    

Upvotes: 12

e_ne
e_ne

Reputation: 8459

IList is not covariant. You can't cast a List<Order> to an IList<Quotable>.

You can change the signature of GetQuotes to:

public void GetQuotes(IEnumerable<IQuotable> quotes)

Then, materialize a list (if you need its features), through:

var list = quotes.ToList();

Upvotes: 9

Related Questions