77

I need some sort of way to store key/value pairs where the value can be of different types.

So I like to do:

 int i = 12;
 string s = "test";
 double x = 24.1;

 Storage.Add("age", i);
 Storage.Add("name", s);
 Storage.Add("bmi", x);

And later retrieve the values with:

 int a = Storage.Get("age");
 string b = Storage.Get("name");
 double c = Storage.Get("bmi");

How should a Storage like this look like? Thanks, Erik

8 Answers 8

95

Well, you could use Dictionary<string, dynamic> in C# 4 / .NET 4 - but other than that, you can't do it with exactly the code shown because there's no type which is implicitly convertible to int, string and double. (You could write your own one, but you'd have to list each type separately.)

You could use Dictionary<string, object> but then you'd need to cast the results:

int a = (int) Storage.Get("age");
string b = (string) Storage.Get("name");
double c = (double) Storage.Get("bmi");

Alternatively, you could make the Get method generic:

int a = Storage.Get<int>("age");
// etc
12
  • Perhaps someone should create a Variant type? HELP, I'M BLIND! Nov 5, 2010 at 11:55
  • 2
    I agree with Jon Skeet. Again. But doing something like this means you are doing something wrong. You should first think about reasons behind why you need to store different values in single dictionary.
    – Euphoric
    Nov 5, 2010 at 11:58
  • Agree wtih Euphoric, would that be easier if just change the dictionary to an Object, and each of value in the list can be a member. Even though it is less dynamic(say you have a large number of uncertain values in the list), it is type safe and easier to maintain.
    – anIBMer
    Dec 9, 2013 at 0:58
  • 4
    @MinhTran: Unless you need to store a variety of values, of course. While it's great if you can make things type-safe, there are all kinds of situations where you really can't.
    – Jon Skeet
    Oct 24, 2018 at 15:53
  • 1
    @BH You need to create the generic extension over Dictionary. It is not there part of .NET so you are not crazy
    – Franck
    Aug 17, 2020 at 15:15
34

You could declare a Dictionary containing just the type object and then cast your results; .e.g.

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

storage.Add("age", 12);
storage.Add("name", "test");
storage.Add("bmi", 24.1);

int a = (int)storage["age"];
string b = (string)storage["name"];
double c = (double)storage["bmi"];

However, this isn't that elegant. If you know you are always going to be storing age, name, bmi I would create an object to encapsulate those and store that instead. E.g.

public class PersonInfo
{
    public int Age { get; set; }
    public string Name { get; set; }
    public double Bmi { get; set; }
}

And then use that insead of the Dictionary... e.g.

PersonInfo person1 = new PersonInfo { Name = "test", Age = 32, Bmi = 25.01 };

int age = person1.Age;

etc.

13

Why not use:

Dictionary<string, object>

You can create an extension method to cast values when you get them:

public static class DictionaryExtensions
{
    public static T Get<T>(this Dictionary<string, object> instance, string name)
    {
        return (T)instance[name];
    }

}

var age = dictionary.Get<int>("age");
5

Given that you don't want a strongly typed data collection then I would have thought a HashTable would be suitable for your situation. You could create an Extention method for this also, like another poster suggested for the Dictionary implementation.

E.g.

public static class StorageExtentions
{
    public static T Get<T>(this Hashtable table, object key)
    {
        return (T) table[key];
    }
}

Your code would then look like:

int i = 12;
string s = "test";
double x = 24.1;
Hashtable Storage = new Hashtable();
Storage.Add("age", i);
Storage.Add("name", s);
Storage.Add("bmi", x);
int a = Storage.Get<int>("age");
string b = Storage.Get<string>("name");
double c = Storage.Get<double>("bmi");
4

maybe it is an old question, but I am addressing the guys who come here to find the answer

if the value is not a fixed type one of the choices is using Hashtable please look at the implementation of both Dictionary and Hashtable

    public class Dictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IReadOnlyDictionary<TKey, TValue>, ICollection, IDictionary, IDeserializationCallback, ISerializable
     {
              ... 
     }

public class Hashtable : ICollection, IEnumerable, IDictionary, ISerializable, IDeserializationCallback, ICloneable
  {
   ...
  }

as it gets more clear from above code snippets, both implement literally the same interfaces but in Hashtable there is no type on both key & value since both of them considered to be intrinsically objects, for example you can see from add method in Hashtable:

public virtual void Add(object key, object value);

so for the cases of not having fixed keys and/or values, I recommend using Hashtable, therefore you don't need to add extra extension methods or override default behavior of a dictionary any more.

2
Dictionary<string, object>
1

You can use a Dictionary<string,object> and then you can put anything you want into it. You would have to cast the results to the right type when you get them out though.

Looking at your example though you might want to consider whether a simple class to store the data might be more what you want and allow better type safety. It depends on whether you have a limited set of things to put in the class or if you do need the potentially unlimited/unknown storage of a dictionary.

1

Dictionary is clearly the quickest solution.

Another way could be to store a custom class in which you could store the actual value and the information regarding its type

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.