2

In my interfaces there is typically an IList<ISomeType> to represent List-type members and to say that I expect an implementation supporting an Add method.

But in the interface implementation, there is an

IList<ISomeType> = new List<ISomeType>()

and everytime I use the List, I have to cast, for example

(this.MyList as List<IMyType>).AddRange(someType.ToList());

Is there a better way to do this? How to avoid this cast?

- edit to ask for more information -

Instead of a extension method, is there a small linq expression to solve that?

IList<string> list = new List<string>();
var items = new[] { "1", "2", "3" };
items.ToList().ForEach(x => list.Add(x));

But this does not look like being very straight forward, as it inverts what is being done. (the action is on the items to add, not on the list).

Anything better than that? Possible something that can be done on the list?

Mare Infinitus
  • 8,024
  • 8
  • 64
  • 113

2 Answers2

5

AddRange is not a method on IList, however Add is, so you can easily make an extension method:

public static void AddRange<T>(this IList<T> list, IEnumerable<T> values) {
    foreach(var value in values)
        list.Add(value);
}

You could also in your extension method check if list is actually an instance of List in which case you can call AddRange directly

Martin Ernst
  • 5,629
  • 2
  • 17
  • 14
  • An extension method is definitly an option. But it does not solve the underlying problem. Should I really use a List instead when I want to say is: "there should be an Add method"? – Mare Infinitus Jul 25 '13 at 10:12
  • 1
    IList has an Add method - it just doesn't have an AddRange method - if you want to be explicit about it, you can create your own interface which inherits from IList and has the method you want, but then you'd have to create your own wrapper class - doesn't seem worth it - from your question it seems like you want the convenience of the AddRange method for your own code, not for a library, hence the suggestion for the extension method. – Martin Ernst Jul 25 '13 at 12:59
0

You could make an extension method suggested by Martin, but this may break stuff.

Why people use interface? To express a public contract. Now this contract is in the .NET BCL framework. If you ever expose the code to external party, you must also expose the extension method and make sure people add a using statement to the file where the extension is. Which may result in a compile time error (Something like "No AddRange method available in the IList<T>").

Additionally the extension method brakes Liskov substitution principle (substitute super type with a base type).

So if you only use List<T> in the methods, you can easily change IList<T> to List<T>.

Community
  • 1
  • 1
oleksii
  • 35,458
  • 16
  • 93
  • 163
  • You are right, the extension method breaks LSP, but I do not want to cast each time. And having a concrete type like List in an interface when I just what to say "there is array that can be added to" does not seem to be the right way either. – Mare Infinitus Jul 25 '13 at 10:14
  • If you just need `Add` consider using [`ICollection`](http://msdn.microsoft.com/en-us/library/92t2ye13.aspx) – oleksii Jul 25 '13 at 11:36
  • this still would end in casts, or not? – Mare Infinitus Jul 25 '13 at 11:43
  • It depends, if you use a single `Add` then no casts needed. If you still want to use `AddRange` then a cast would be required. – oleksii Jul 25 '13 at 13:15