Using an Dictionary<string, object> as Dictionary<string, Dictionary<string, string>>

38,421

Solution 1

By using object as the value in your dictionary you will incur some risk and complications:

  • Lack of type safety (anything can be set to the value)
  • You would have to cast to a particular type, probably based on the value

You should probably rethink your design. But if you really want a the flexibility you could create a new type that would work as the value type. Something like:

class MySpecialType
{
    public Dictionary<string, string> MyStringDictionary { get; set; }
    public string MyStringVal {get; set;}

    public Type ActiveType { get; set; } // property would specify the current type
    // ...

Your main dictionary declaration would then look something like:

Dictionary<string, MySpecialType> MyDict = new Dictionary<string, MySpecialType>();

You could use the ActiveType property or create an enum which would specify the type. You could also have static util functions in the class which could help with returning the right instance and type...

Solution 2

Yes, your dictionary would not be strongly typed anymore - in the first approach you could do something like:

string value = myDict["foo"]["bar"];

In the second approach this is not possible anymore since you have to cast first:

string value = ((Dictionary<string,string>)myDict["foo"])["bar"];

It sounds like your problem could be solved with a better design approach. Usually the need to store different kind of objects in the same data structure can be avoided by re-designing the solution - so why do you need to do this?

Edit:

If you just want to handle null values you could just do something like:

string value = myDict["foo"] != null ? myDict["foo"]["bar"] : null;

Or wrapped in an extension method:

public static T GetValue<T>(this Dictionary<T, Dictionary<T,T>> dict, 
                            T key, T subKey) where T: class
{
    T value = dict[key] != null ? dict[key][subKey] : null;
    return value;
}

string value = myDict.GetValue("foo", "bar");

Solution 3

You can do that. After retrieving data from the main dictionary, you will have to cast the result to an appropriate type:

object obj;
If(mainDict.TryGetValue("key", out obj)) {
    var dict = obj as Dictionary<string, string>>;
    if (dict != null) {
        // work with dict
    } else {
        var value = obj as MyOtherType;
        ....
    }
}

But note that this is not type-safe; i.e., the compiler can only partially check the validity of your code regarding the values of type object.


Alternatively you could try a more object-oriented solution

public abstract class MyBaseClass 
{
    public abstract void DoSomething();
}

public class MyDictClass : MyBaseClass
{
    public readonly Dictionary<string, string> Dict = new Dictionary<string, string>();

    public override void DoSomething()
    {
        // So something with Dict
    }
}

public class MyTextClass : MyBaseClass
{
    public string Text { get; set; }

    public override void DoSomething()
    {
        // So something with Text
    }
}

Then declare your main dictionary with

var mainDict = new Dictionary<string, MyBaseClass>();

mainDict.Add("x", new MyDictClass());
mainDict.Add("y", new MyTextClass());

...

MyBaseClass result = mainDict[key];
result.DoSomething(); // Works for dict and text!

Solution 4

You'll loose strong types and all their benefits.

Can you not create a new class that has a Dictionary property and add your other data to it:

public class CallItWhatYouLike
{
  public Dictionary<string, string> Dictionary {get; set;}
  public int AnotherProperty {get; set;}
  ...
}

var MyDict = new Dictionary<string, CallItWhatYouLike>();
Share:
38,421
N471v3
Author by

N471v3

Updated on October 29, 2020

Comments

  • N471v3
    N471v3 over 3 years

    in C# I need to keep data in a dictionary object, looks like:

    Dictionary<string, Dictionary<string, string>> MyDict = 
        new Dictionary<string, Dictionary<string, string>>();
    

    Now I realised, that I would need in some cases some other (not dictionary-like) data as value of the main dict.

    Is there any kind of Problem or limitation, if I just instance the main dict. as:

    Dictionary<string, object> MyDict = new Dictionary<string, object>();
    

    in the object field I could put string, dictionary, whatever..

    Thanks in advance, Best regards, Steven

  • N471v3
    N471v3 about 12 years
    Because this is implemented all over some 1000 lines of code, and for some cases there was the need to add values with null, where the key was used as data. like: MyDict.Add("One_key", AnotherDictionary); MyDict.Add("Cool_key", null); than in for-loop: if(MyDict.value != null) //do something And your point is right, the design is maybe a bit faulty! But I need the key and the value field for data now, and thought I do not want to make a sub-dictionary for these key value pair eintries with value null, because of code overhead, if you know what I mean. (many entries with null-value)
  • N471v3
    N471v3 about 12 years
    Your answear in combination with the knowledge of the others makes most sense for me. (thanks for that!) "Lack of type safety (anything can be set to the value)" would be a feature for me in that case :D Your solution with the class makes sense, but is a bit like the overhead I tried to avoid for me. So solved, thanks to all, my main Problem is the context and design of the code. THANKS