N471v3
N471v3

Reputation: 57

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

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

Upvotes: 3

Views: 49271

Answers (7)

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112782

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!

Upvotes: 5

BrokenGlass
BrokenGlass

Reputation: 161012

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");

Upvotes: 5

Paul Sasik
Paul Sasik

Reputation: 81567

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...

Upvotes: 3

SliverNinja - MSFT
SliverNinja - MSFT

Reputation: 31651

You will pay a performance penalty when you unbox the System.Object, but other than that there isn't a problem with your approach other than excessive casting for indexers (due to weak typing).

You may consider using a System.Tuple if you are using .NET 4.

Upvotes: 0

vc 74
vc 74

Reputation: 38179

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>();

Upvotes: 1

wRAR
wRAR

Reputation: 25569

Well, your code will be less typesafe and you will need runtime type checks and type casts, but otherwise you can use object as a dictionary value type and store any types there.

Upvotes: 0

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

Reputation: 64943

No, there's no problem. If you need to type the value as Dictionary<string, string> just cast it and you'll have this solved.

Upvotes: 0

Related Questions