Allan Simonsen
Allan Simonsen

Reputation: 1238

Unable to cast Dictionary<string, string> to class descended from Dictionary<string, string>

I have a complex data structure with nested dictionaries. Something like this: Dictionary<string, Dictionary<string, Dictionary<string, string>>> which is not readable at all, so my thought was to create classes descending from Dictionary<.., ..> and improve readability by casting the dictionaries to these classes. Something like this:

private class MyKeyValues : Dictionary<string, string> {}
private class MyAssetKeyValues : Dictionary<string, MyKeyValues> {}

My problem boils down to the code below which compiles, but fails runtime with a casting exception. Why is what i'm trying to do failling? And is there a workaround to improve the readability of those nested dictionaries?

using System;
using System.Collections.Generic;

namespace ConsoleApp1
{
    public class MyDictionary : Dictionary<string, string> { }

    public static class Program
    {
        public static void Main(string[] args)
        {
            var dictionary = new Dictionary<string, string>
            {
                { "DummyKey1", "DummyVal1"},
                { "DummyKey2", "DummyVal2"},
            };
            var myDictionary = (MyDictionary)dictionary;
            foreach (var key in myDictionary.Keys)
            {
                Console.WriteLine($"Key: {key}, Val: {myDictionary[key]}");
            };
        }
    }
}

Upvotes: 0

Views: 633

Answers (1)

Jamiec
Jamiec

Reputation: 136154

I'll start with this - almost every time I see someone inherit from Dictionary (or List for that matter!) it's almost always the wrong thing to do. Inheritance implies an is-a link, whereas what you almost always want is a has-a relationship. Composition. Your class MyAssetKeyValues should contain a Dictionary not inherit from Dictionary.

Then, all this becomes simple. You class might take a Dictionary as a constrictor argument, allowing you to construct one from a Dictionary

private class MyKeyValues 
{
    private readonly Dictionary<string,string> dict;

    public MyKeyValues(Dictionary<string,string> dict){ this.dict = dict; }
}

var dictionary = new Dictionary<string, string>
{
    { "DummyKey1", "DummyVal1"},
    { "DummyKey2", "DummyVal2"},
};
var myDictionary = new MyKeyValues(dictionary);

Note that you can still make your class behave like a dictionary by implementation detail. And you can nest these as much as you like:

private class MyAssetKeyValues {
    private readonly  Dictionary<string, MyKeyValues> dict;

    // .... //
}

Upvotes: 1

Related Questions