16

From msdn:

Represents a generic read-only collection of key/value pairs.

However consider following:

class Test
{
    public IReadOnlyDictionary<string, string> Dictionary { get; } = new Dictionary<string, string>
    {
        { "1", "111" },
        { "2", "222" },
        { "3", "333" },
    };

    public IReadOnlyList<string> List { get; } =
        (new List<string> { "1", "2", "3" }).AsReadOnly();
}

class Program
{
    static void Main(string[] args)
    {
        var test = new Test();

        var dictionary = (Dictionary<string, string>)test.Dictionary; // possible
        dictionary.Add("4", "444"); // possible
        dictionary.Remove("3"); // possible

        var list = (List<string>)test.List; // impossible
        list.Add("4"); // impossible
        list.RemoveAt(0); // impossible
    }
}

I can easily cast IReadOnlyDictionary to Dictionary (anyone can) and change it, while List has nice AsReadOnly method.

Question: how to properly use IReadOnlyDictionary to make public indeed read-only dictionary ?

Sinatr
  • 19,902
  • 11
  • 86
  • 275
  • I think creating an *Adapter* over the `Dictionary` can help to expose only the **read-only** behaviour. – adricadar Sep 14 '15 at 08:50
  • You're misunderstanding what an interface does. It just describes a contract. `IList` could inherit `IReadOnlyCollection`, for example, but that doesn't make the list implementing `List` read-only. Is your actual question _"How can I make a read-only dictionary"_? – CodeCaster Sep 14 '15 at 08:50
  • @CodeCaster, hmm, yes. But not *making* it myself, rather reuse existing in .net type properly. – Sinatr Sep 14 '15 at 08:52
  • @adricadar, I am using properties. – Sinatr Sep 14 '15 at 08:54

1 Answers1

19

.NET 4.5 introduced the ReadOnlyDictionary type that you could use. It has a constructor that accepts an existing dictionary.

When targeting lower framework versions, use the wrapper as explained in Is there a read-only generic dictionary available in .NET? and Does C# have a way of giving me an immutable Dictionary?.

Please note that when using the latter class, the collection initializer syntax won't work; that gets compiled to Add() calls.

Community
  • 1
  • 1
CodeCaster
  • 139,522
  • 20
  • 204
  • 252
  • 1
    Didn't noticed `ReadOnlyDictionary` (it's well hidden), thanks. I can use normal `Dictionary` with collection initializer as a constructor parameter for `ReadOnlyDictionary`. – Sinatr Sep 14 '15 at 09:00
  • 2
    You could also use [`ImmutableDictionary<>`](https://msdn.microsoft.com/en-us/library/dn467181%28v=vs.111%29.aspx) if you're using the latest version of .Net. (That's a hardcore immutable class ;) – Matthew Watson Sep 14 '15 at 09:02
  • @MatthewWatson, good to know, thanks. I wonder what is a difference, but that would be another question, right? – Sinatr Sep 14 '15 at 09:06
  • 2
    @Sinatr `ImmutableDictionary<>` is not a wrapper class and it is truely immutable,. `ReadOnlyDictionary` is only a wrapper and it's important to note that if you change the contents of the wrapped dictionary, the contents of the read-only dictionary also change. It's read-only, not immutable! – Matthew Watson Sep 14 '15 at 09:16
  • @MatthewWatson, thanks for explanation. I am not going to change dictionary content after creating instance (writable dictionary instance is not stored and `ReadOnlyDictionary.Dictionary` property is `protected`), so *read-only* is all I need. The idea with `ToBuilder() / ToImmutable()` is nice (multithreading?), might use `ImmutableDictionary` some day. – Sinatr Sep 14 '15 at 09:42