Introduction
In the preceding hierarchical diagram, you can see core generic interfaces and read-only interfaces. I assume you are familiar with core generic interfaces, so here I'm not discussing more of them. Read-only interfaces were introduced only recently with .NET 4.5 They essentially have all the functionality for modifying collections from generic interfaces removed, letting you expose interfaces to other code without any risk of that code being able to use those interfaces to modify collections.
Look at the read-only part of the hierarchy. The read-only interfaces start with an interface called IReadOnlyCollection that mirrors ICollection. We saw that the main branch splits into three at this point. The read-only interfaces do the same thing except that there's no read-only equivalent of ISet. The only read-only interfaces are IReadOnlyList and IReadOnlyDictionary. As I said earlier, read-only interfaces do not expose anything to modify the collection.
IReadOnlyCollection<T>
This is a very simple interface. We can start with ICollection. You can see the ICollection interface in the following sample.
Remove all the stuff to do the modification of the collection and we also remove the Contains() and CopyTo() methods.
So what are we left with? Yes, the Count property. IReadOnlyCollection is enumerable that also knows how many elements it has and I think that's potentially rather a nice interface to have available.
Example
IReadOnlyList<T>
IRedOnlyList follows the spirit of IReadOnlyCollection. It adds those IList methods that are read-only and unambiguously useful and this is the result. You get IReadOnlyCollection plus the indexer, but only read-only access and that's it. In the following picture, you can see the IReadOnlyList<T> interface.
Example
IReadOnlyDictionary<TKey, TValue>
IReadOnlyDictionary is unusual for read-only interfaces and is quite powerful. It contains all the added functionality of IDictionary except obviously for the ability to add or remove items. In the following sample, you can see the IDictionary interface.
You can see the IReadOnlyDictionary<Tkey, TValue> interface below.
public interface IReadOnlyDictionary<TKey, TValue> : IReadOnlyCollection<KeyValuePair<TKey, TValue>>,
IEnumerable<KeyValuePair<TKey, TValue>>,
IEnumerable
{
IEnumerable<TKey> Keys
{
get;
}
IEnumerable<TValue> Values
{
get;
}
TValue this[TKey key]
{
get;
}
bool ContainsKey(TKey key);
bool TryGetValue(TKey key, out TValue value);
}
The IReadOnlyDictionary<Tkey, TValue> interface looks quite nice and useful if you want to expose read-only functionality on a Dictionary.
Conclusion
Read-only interfaces look quite nice and useful if you want to expose read-only functionality on core generic-type interfaces like ICollection<T>, IList<T>, and IDictionary<Tkey, Tvalue>.