たまに触るとIReadOnlyList<T>とIReadOnlyCollection<T>とReadOnlyCollection<T>の関係を忘れてしまうので、メモです。
ReadOnlyCollection<T>
そもそもReadOnlyCollection<T>クラスのネーミングが悪い気がしますが、これはIReadOnlyCollection<T>インターフェイスとセットのクラスではありません。ドキュメントを見れば一目瞭然ですが、これはIReadOnlyCollection<T>だけでなく、IReadOnlyList<T>も実装しています。
IReadOnlyCollection<T>とIReadOnlyList<T>の違いはインデクサーの有無で、IReadOnlyCollection<T>にはインデクサーはないのに、ReadOnlyCollection<T>にはインデクサーがあるので混乱しますが、そもそもReadOnlyCollection<T>はIReadOnlyCollection<T>用とIReadOnlyList<T>用のクラスを兼ねていて、どちらのインターフェイスでアクセスするかでインデクサーへのアクセス可否が変わるというだけということです。
これはドキュメントに当たればすぐに分かる話ですが、得てしてコードをいじっているだけでは、ReadOnlyList<T>というクラスがないこと、List用のList<T>.AsReadOnly()メソッドも、Array用のArray.AsReadOnly<T>(T[])メソッドも生成されるのはReadOnlyCollection<T>ということの理由にたどり着かないのですよね。
Dictionary<TKey, TValue>のReadOnly化
Dictionary<TKey, TValue>からReadOnlyDictionary<TKey, TValue>クラスをコンストラクターで生成した場合、TValueがListやArrayなどのコレクションの場合、そのままではコレクションの要素は当然ReadOnlyにはなりません。したがって、一旦TValueをReadOnlyCollection<T>に変換した上で、インデクサーの必要性に応じてIReadOnlyList<T>かIReadOnlyCollection<T>にキャストする必要があります。
Listの場合
var d1 = new Dictionary<string, List<int>>();
...
IReadOnlyDictionary<string, IReadOnlyList<int>> d2 =
new ReadOnlyDictionary<string, IReadOnlyList<int>>(d1.ToDictionary(
x => x.Key,
x => (IReadOnlyList<int>)x.Value.AsReadOnly()));
var d1 = new Dictionary<string, List<int>>();
...
IReadOnlyDictionary<string, IReadOnlyCollection<int>> d2 =
new ReadOnlyDictionary<string, IReadOnlyCollection<int>>(d1.ToDictionary(
x => x.Key,
x => (IReadOnlyCollection<int>)x.Value.AsReadOnly()));
Arrayの場合
var d1 = new Dictionary<string, int[]>();
...
IReadOnlyDictionary<string, IReadOnlyList<int>> d2 =
new ReadOnlyDictionary<string, IReadOnlyList<int>>(d1.ToDictionary(
x => x.Key,
x => (IReadOnlyList<int>)Array.AsReadOnly(x.Value)));
var d1 = new Dictionary<string, int[]>();
...
IReadOnlyDictionary<string, IReadOnlyCollection<int>> d2 =
new ReadOnlyDictionary<string, IReadOnlyCollection<int>>(d1.ToDictionary(
x => x.Key,
x => (IReadOnlyCollection<int>)Array.AsReadOnly(x.Value)));
やや面倒ですが、こんな感じかと思います。なお、TValueがNullの可能性がある場合は、ReadOnlyCollection<T>に変換する前にNullチェックも必要になります。