AquaGeneral
AquaGeneral

Reputation: 155

Save Dictionary Key inside Value class

Imagine code like the following:

Dictionary<string, MyClass> dictionary = new Dictionary<string, MyClass>() {
    { "Name 1", new MyClass("Name 1", "Second Value 1") },
    { "Name 2", new MyClass("Name 2", "Second Value 2") },
    { "Name 3", new MyClass("Name 3", "Second Value 3") }
}

I need MyClass to store the key (eg "Name 1") as a field. I'd also like the flexibility of the Dictionary for what I'm doing (taking advantage of accessing an item by a key).

I can't figure out a way of accomplishing what I want without specifying the key twice like in the code above.

Any ideas on how to solve this?

Upvotes: 0

Views: 304

Answers (3)

Gergely Hamos
Gergely Hamos

Reputation: 411

What you want is actually a bidirectional mapping between the objects and their names, therefore under the hood the keys have to be stored twice (in both mapping directions), but you can hide the behavior with:

1) extension methods

public static void Add(this Dictionary<string, MyClass> dictionary, Myclass obj){
    dictionary.Add(obj.name, obj);
}

2) Or by deriving a class from Dictionary and write new functions to add and modify stored objects (like the extension method above).

class A : Dictionary<String, MyClass>
{
    public void Add(MyClass m)
    {
        this.Add(m.Name,m);
    }
}

*This case it will also work, which is what you really want, I think:

A a = new A() {new MyClass("name", "second value") };

3) Writing implicit conversion operators for myClass to KeyValuePair and vice-versa. In this case you can use MyClass instances like KeyValuePairs with your dictionary (except in initializer list!).

class MyClass
{

// ...other members 

public static implicit operator KeyValuePair<string,MyClass>(MyClass obj)
{
    return new KeyValuePair<string,MyClass>(obj.Name,obj);
}

public static implicit operator MyClass(KeyValuePair<string,MyClass> kvp)
{
    return kvp.Value;
}

}

Feel free to use and combine the methods above.

Upvotes: 1

TVOHM
TVOHM

Reputation: 2742

Another LINQ-esque solution using ToDictionary (avoiding the need for a field):

var dictionary = new[] { "Name 1", "Name 2", "Name 3" }
    .ToDictionary(k => k, v => new MyClass(v, "Second Value"));

But this might not be appropriate given you requirements on "Second Value".

EDIT:

Alternative solution if you have naming criteria for the second parameter:

var dictionary = Enumerable.Range(1, 3)
    .ToDictionary(k => "Name " + k, v => new MyClass("Name " + v, "Second Value " + v));

Upvotes: 0

Matias Cicero
Matias Cicero

Reputation: 26281

You can create all your MyClass instances in an array and then convert said array into a dictionary using LINQ:

Dictionary<string, MyClass> dictionary = new MyClass[]
{
    new MyClass("Name 1", "Second Value 1"),
    new MyClass("Name 2", "Second Value 2"),
    new MyClass("Name 3", "Second Value 3")
}.ToDictionary(c => c.NameProperty, c => c);

Note that NameProperty should be the property that holds the dictionary's key (The one that holds these "Name X" values)

Upvotes: 2

Related Questions