# IEnumerable<T>, IReadOnlyList<T>, IList<T> — the collection interfaces

> C#'s collection interfaces are accepted wherever a type is written, each as the collection it names: IEnumerable<T>, IReadOnlyList<T> and IReadOnlyCollection<T> are a read-only sequence (T[]), IList<T> and ICollection<T> a List<T>, ISet<T> a HashSet<T>, IDictionary<K, V> a Dictionary<K, V>. A List<T> passes where a read-only sequence is asked for.

<!-- id: types-collection-interfaces · area: types · stability: stable · html: https://osysharp.com/reference/types/collection-interfaces/ -->

## Summary        {#summary}
Write the interface C# code writes; it means the collection it names:

```osy title="interfaces as parameter, return and local types" run app=types-collection-interfaces
int Total(IEnumerable<int> xs) {
  int t = 0;
  foreach (var x in xs) { t += x; }
  return t;
}

void AddTo(IList<string> names, string name) { names.Add(name); }

IEnumerable<int> Evens(List<int> xs) => xs.Where(x => x % 2 == 0);

[Test]
void Interfaces_Are_The_Collections_They_Name() {
  Assert.Equal(3, Total(new List<int> { 1, 2 }));     // a List passes for a read-only sequence
  var names = new List<string>();
  AddTo(names, "Ada");
  Assert.Equal(1, names.Count);
  IReadOnlyList<int> evens = Evens(new List<int> { 1, 2, 3, 4 }).ToList();
  Assert.Equal(2, evens.Count());
}
```

## Signature      {#signature}
```osy syntax
IEnumerable<T> / IReadOnlyList<T> / IReadOnlyCollection<T>   // the read-only sequence: T[]
IList<T> / ICollection<T>                                     // List<T>
ISet<T> / IReadOnlySet<T>                                     // HashSet<T>
IDictionary<K, V> / IReadOnlyDictionary<K, V>                 // Dictionary<K, V>
```

## Description    {#description}

### What is the difference from C#?   {#differences}
Osy# has no interface OVER its collections, so each interface is exactly one collection rather than a promise any
collection can keep. The read-only ones are the array, which is read-only by construction; the mutable ones are the
list. A value of the other kind converts where C# would accept it — a `List<T>` passes for an `IEnumerable<T>`.

`IQueryable<T>` is different: it is a QUERY over stored rows, not a collection in hand ([Query<T>](https://osysharp.com/reference/query/deferred/)).

## See also       {#see-also}
- [IEnumerable<T> with yield return — iterators](https://osysharp.com/reference/function/iterators/) — `IEnumerable<T>` with `yield return`
- [Query<T>](https://osysharp.com/reference/query/deferred/) — `IQueryable<T>`, a query not yet run
