Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary with object as value

I'm going nuts here. It's probably because I've missed some rule, but if so, then please tell me.

I'm trying to create a Dictionary with a string for key and an anonymous object as value. Or, actually I'm not just trying, I'm doing it. But when I want to alter a specific parameter in the object, it goes wrong.

I declare the dictionary like this:

var areas = new Dictionary<string, object>
{
  {"Key1", new {name = "Name1", today = 0, all = 0}},
  {"Key2", new {name = "Name2", today = 0, all = 0}},
    ...
}

And then I'm assuming I can do this:

foreach (var area in areas.Keys.ToArray())
{
    var areaname = areas[area].name;
}

but Visual Studio does not agree, and refuses to compile. If I write this, though, everything works as I would think - but that doesn't really help me out, it's just making me more frustrated.

var areaname = new 
            {
                 name = "Nametest", today = 0, all = 0
            };
var testname = areaname.name;

What am I doing wrong? Why isn't it working for me? Is it simply impossible to do so?

Thanks for all your answers, they surely cleared things up a bit! I think I might have been confusing the type object with the idea of objects, that is classes, in C# out of frustration. I'll rethink the whole design business and probably do something completely different instead of using evil or dirty solutions. Though interesting, I don't think my relationship with C# has evolved that far yet!

like image 218
DummeDitte Avatar asked Sep 06 '11 14:09

DummeDitte


People also ask

Can an object be a value in a dictionary Python?

A dictionary value can be any object (even the dictionary itself!

Can dictionary value be a Object C#?

You can create the Dictionary<TKey, TValue> object by passing the type of keys and values it can store. The following example shows how to create a dictionary and add key-value pairs. In the above example, numberNames is a Dictionary<int, string> type dictionary, so it can store int keys and string values.

Can dictionaries contain objects?

The dictionary stores objects as key-value pairs and can be used to represent complex real-world data.

Can a list be a value in a dictionary Python?

A Python dictionary is a collection of key-value pairs where each key is associated with a value. A value in the key-value pair can be a number, a string, a list, a tuple, or even another dictionary. In fact, you can use a value of any valid type in Python as the value in the key-value pair.


2 Answers

This will not work because you have declared the dictionary as Dictionary<string, object>.

You could instead try Dictionary<string, dynamic>.

like image 97
Andras Zoltan Avatar answered Oct 02 '22 19:10

Andras Zoltan


This will not work because you have declared the dictionary as Dictionary<string, object>.

C# creates a new type in the background for you (which you can't access) that has these properties (herewith known as an anonymous type). The only time you can use it directly is when it is still var type - as soon as you add it to that dictionary it is cast to object and thus you can't access the properties any more.

Option 1

You could instead try Dictionary<string, dynamic>. Dynamic will be able to access these properties - but this is only supported in C#/.Net 4.0

Option 2

You can get the type back using a technique known as demonstration (cast by example). This isn't a documented feature, is wasteful and is somewhat a hack. This is a horrible evil trick - especially because it won't work across assemblies.

public static T Demonstrate<T>(this T demonstration, object value)
{
    return (T)value;
}

You can then access the original properties like so:

var area = new { name = "", today = 0, all = 0 }.Demonstrate(areas[name]);
var areaName = value.name;

Option 3 This is honestly the best way

Write a class. If you like the fact that the C# compiler does all of the Equals, GetHashCode and ToString work for you, you can just use something like ILSpy to grab the original code. Thus:

class AreaInfo
{
    public string Name { get; set; }
    public int Total { get; set; }
    public int All { get; set; }

    public override bool Equals(object obj)
    {
        var ai = obj as AreaInfo;
        if (object.ReferenceEquals(ai, null))
            return false;
        return Name == ai.Name && Total == ai.Total && All == ai.All;
    }

    public override int GetHashCode()
    {
        var hc = 0;
        if (Name != null)
            hc = Name.GetHashCode();
        hc = unchecked((hc * 7) ^ Total);
        hc = unchecked((hc * 21) ^ All);
        return hc;
    }

    public override string ToString()
    {
        return string.Format("{{ Name = {0}, Total = {1}, All = {2} }}", Name, Total, All);
    }
}

Correct your dictionary:

var areas = new Dictionary<string, AreaInfo>       
{       
  {"Key1", new AreaInfo() {Name = "Name1", Today = 0, All = 0}},       
  {"Key2", new AreaInfo() {Name = "Name2", Today = 0, All = 0}},       
    ...       
};

And now things will work the way you expect them to.

like image 35
Jonathan Dickinson Avatar answered Oct 02 '22 21:10

Jonathan Dickinson