Start here. This is the direct spoken answer to practice first.
Why this question matters
The type in a method signature tells callers which operations are reliable. Accepting or returning a broader abstraction than the behavior supports creates hidden enumeration and complexity assumptions.
I choose the interface from the operations the method actually requires. IEnumerable<T> represents a sequence and may be lazy or one-shot; it does not promise cheap counting, indexing, or repeatable enumeration. IReadOnlyCollection<T> adds a count, and IReadOnlyList<T> adds indexed access without promising that another owner cannot change the backing collection. IReadOnlySet<T> expresses uniqueness and membership, while IReadOnlyDictionary<TKey,TValue> expresses keyed lookup. I use mutable ISet<T> or IDictionary<TKey,TValue> only when mutation is intentionally part of the method's contract.