Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IList<T> and IReadOnlyList<T>

If I have a method that requires a parameter that,

  • Has a Count property
  • Has an integer indexer (get-only)

What should the type of this parameter be? I would choose IList<T> before .NET 4.5 since there was no other indexable collection interface for this and arrays implement it, which is a big plus.

But .NET 4.5 introduces the new IReadOnlyList<T> interface and I want my method to support that, too. How can I write this method to support both IList<T> and IReadOnlyList<T> without violating the basic principles like DRY?

Edit: Daniel's answer gave me some ideas:

public void Foo<T>(IList<T> list)     => Foo(list, list.Count, (c, i) => c[i]);  public void Foo<T>(IReadOnlyList<T> list)     => Foo(list, list.Count, (c, i) => c[i]);  private void Foo<TList, TItem>(     TList list, int count, Func<TList, int, TItem> indexer)     where TList : IEnumerable<TItem> {     // Stuff } 

Edit 2: Or I could just accept an IReadOnlyList<T> and provide a helper like this:

public static class CollectionEx {     public static IReadOnlyList<T> AsReadOnly<T>(this IList<T> list)     {         if (list == null)             throw new ArgumentNullException(nameof(list));          return list as IReadOnlyList<T> ?? new ReadOnlyWrapper<T>(list);     }      private sealed class ReadOnlyWrapper<T> : IReadOnlyList<T>     {         private readonly IList<T> _list;          public ReadOnlyWrapper(IList<T> list) => _list = list;          public int Count => _list.Count;          public T this[int index] => _list[index];          public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();          IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();     } } 

Then I could call it like Foo(list.AsReadOnly())


Edit 3: Arrays implement both IList<T> and IReadOnlyList<T>, so does the List<T> class. This makes it pretty rare to find a class that implements IList<T> but not IReadOnlyList<T>.

like image 372
Şafak Gür Avatar asked Oct 11 '12 11:10

Şafak Gür


People also ask

What is IReadOnlyCollection C#?

The IReadOnlyCollection interface extends the IEnumerable interface and represents a basic read-only collection interface. It also includes a Count property apart from the IEnumerable members as shown in the code snippet given below.


1 Answers

You are out of luck here. IList<T> doesn't implement IReadOnlyList<T>. List<T> does implement both interfaces, but I think that's not what you want.

However, you can use LINQ:

  • The Count() extension method internally checks whether the instance in fact is a collection and then uses the Count property.
  • The ElementAt() extension method internally checks whether the instance in fact is a list and than uses the indexer.
like image 66
Daniel Hilgarth Avatar answered Oct 05 '22 12:10

Daniel Hilgarth