Why does IDictionary not implement IReadOnlyDictionary

I've recently just noticed that IDictionary does not implement IReadOnlyDictionary. I'm using two third-party libraries, one of which provides a ToDictionary() method which returns an IDictionary containing the contents, and another which consumes an IReadOnlyDictionary. In order to make this work, I've had to write the following ugly code: // IDictionary does not implement IReadOnlyDictionary, so we have to call .ToDictionary() // again to get a concrete dictionary implementation. var errors = result.ToDictionary().ToDictionary(x => x.Key, x => x.Value); From looking at the two interfaces, it seems that the methods in IReadOnlyDictionary are a direct subset of IDictionary: // Represents a generic read-only collection of key/value pairs. public interface IReadOnlyDictionary : IEnumerable, IEnumerable, IReadOnlyCollection { TValue this[TKey key] { get; } IEnumerable Keys { get; } IEnumerable Values { get; } bool ContainsKey(TKey key); bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value); } // Represents a generic collection of key/value pairs. public interface IDictionary : ICollection, IEnumerable, IEnumerable { TValue this[TKey key] { get; set; } ICollection Keys { get; } ICollection Values { get; } void Add(TKey key, TValue value); bool ContainsKey(TKey key); bool Remove(TKey key); bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value); } Some notable differences: The array index operator is get in the read-only version, and get/set in the writeable version. Would it be possible to specify this if inheriting from IReadOnlyDictionary? The Keys and Values are IEnumerable in the read-only version, and ICollection in the writeable version. This also doesn't make sense to me. When would you add a key to a dictionary without a value, or add a value to a dictionary without a key? I feel like it would make more sense for the writeable dictionary to also return IEnumerable or IReadOnlyCollection for these properties. The .Net team put a lot of thought into the core classes, so I assume the interfaces are separate by design. Does anyone know why the interfaces were created this way?

Feb 2, 2025 - 11:43
 0
Why does IDictionary not implement IReadOnlyDictionary

I've recently just noticed that IDictionary does not implement IReadOnlyDictionary. I'm using two third-party libraries, one of which provides a ToDictionary() method which returns an IDictionary containing the contents, and another which consumes an IReadOnlyDictionary. In order to make this work, I've had to write the following ugly code:

// IDictionary does not implement IReadOnlyDictionary, so we have to call .ToDictionary()
// again to get a concrete dictionary implementation.
var errors = result.ToDictionary().ToDictionary(x => x.Key, x => x.Value);

From looking at the two interfaces, it seems that the methods in IReadOnlyDictionary are a direct subset of IDictionary:

// Represents a generic read-only collection of key/value pairs.
public interface IReadOnlyDictionary : IEnumerable>, IEnumerable, IReadOnlyCollection>
{
    TValue this[TKey key] { get; }
    IEnumerable Keys { get; }
    IEnumerable Values { get; }
    bool ContainsKey(TKey key);
    bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value);
}

// Represents a generic collection of key/value pairs.
public interface IDictionary : ICollection>, IEnumerable>, IEnumerable
{
    TValue this[TKey key] { get; set; }
    ICollection Keys { get; }
    ICollection Values { get; }
    void Add(TKey key, TValue value);
    bool ContainsKey(TKey key);
    bool Remove(TKey key);
    bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value);
}

Some notable differences:

  • The array index operator is get in the read-only version, and get/set in the writeable version. Would it be possible to specify this if inheriting from IReadOnlyDictionary?
  • The Keys and Values are IEnumerable in the read-only version, and ICollection in the writeable version. This also doesn't make sense to me. When would you add a key to a dictionary without a value, or add a value to a dictionary without a key? I feel like it would make more sense for the writeable dictionary to also return IEnumerable or IReadOnlyCollection for these properties.

The .Net team put a lot of thought into the core classes, so I assume the interfaces are separate by design. Does anyone know why the interfaces were created this way?