tags:

views:

155

answers:

8

This is more of an academic inquiry than a practical question. Are there any language or framework features that can, or will in future, allow a heterogeneous typed dcitionary, e.g.

myDict.Add("Name", "Bill"); 
myDict.Add("Height", 1.2);

where myDict now contains not two object types as values, but one string and one double? I could then retrieve my double with

double dbl = myDict["Height"];

and expect a double or an exception to be thrown?

Please note: The Name and Height values are not necessarily of the same object.

+1  A: 

You can use Generic Dictionary<object, object>; object type for key and object type for value. C# could help.

yapiskan
A: 

Any reason you can't make a class / struct and put that into a list or dictionary? Otherwise you could just wrap the dictionary class with your own and put the restrictions in that way.

smack0007
A: 

Why not simply store all values as strings, convert them when you retrieve them, and catch exceptions from that conversion?

I don't see why you would need to do things this way - perhaps a redesign of your program is warranted?

Bork Blatt
I don't need to do things this way. I don't need to do anything except explore what could be done.
ProfK
A: 

The keys are all strings? then Dictionary<string,object> would probably do the job... but when getting values out, you would either need to use object, or you'd need to cast:

double dbl = (double)myDict["Height"];
object height = myDict["Height"];
Marc Gravell
The very reason I asked the question was to avoid having dic values as objects. If I store a double, I want a double back, not a 'double exposing object' that I must cast.
ProfK
@Profk - you are fooling yourself if you think that Get<int>(...) is any different to (int) Get(...). Oh well...
Marc Gravell
+1  A: 

If the types are classes there's nothing to stop you interfacing both and putting the instances in a dictionary <foo, IYourInterface>

annakata
Maybe. Maybe something like IPresentationElementValue. Food for thought.
ProfK
A: 

The dictionary WILL contain a string and a double as values, but the double will be boxed.

How could the compiler validate what you're asking? How could it know at compile time which type of object relates to each key?

Winston Smith
The idea is not to know at compile time, but to use the key to determine the return type. C# is moving toward including some exciting dynamic concepts, and I believe this could fall under the shadow of that.
ProfK
+1  A: 

A Dictionary is not the way to do it.
You really want a Person class for storing those values.

And, it is much easier to both create collections and catch errors with classes.

EDIT:

Since you need a semi-strongly typed dict:

public class CustomDictionary : Dictionary<string,object>
{
    public T GetTyped<T>(string key) where T : IConvertible
    {
        return (T)Convert.ChangeType(base[key], typeof (T));
    }
}

Usage:

CustomDictionary dictionary = new CustomDictionary();

dictionary.Add("Test",1.2);

var d = dictionary.GetTyped<double>("Test");
Lars Mæhlum
The values need not be coupled to the same object, as my example accidentally implied. Name could be that of a dog, and Height that of a table.
ProfK
Oh, ok. You want a CustomDictonary that extends Dictionary<string,object> and Adds a GetTyped<Type>(string key) method :)
Lars Mæhlum
Yes, very nice thanks!
ProfK
+3  A: 

The only way you'll be able to do this if you have a custom collection with generic overloads for Add and Get methods. But that would mean you can ask for the wrong type when reading the key out, so it doesn't gain you much (if anything) over doing the cast yourself when you call your Get method.

However, if you can push the generic type into the key then that could work. Something like (untested code here)

sealed class MyDictionaryKey<T>
{
}

class MyDictionary
{
    private Dictionary<object, object> dictionary = new Dictionary<object, object>();

    public void Add<T>(MyDictionaryKey<T> key, T value)
    {
        dictionary.Add(key, value);
    }

    public bool TryGetValue<T>(MyDictionaryKey<T> key, out T value)
    {
      object objValue;
      if (dictionary.TryGetValue(key, out objValue))
      {
        value = (T)objValue;
        return true;
      }
      value = default(T);
      return false;
    }

    public T Get<T>(MyDictionaryKey<T> key)
    {
      T value;
      if (!TryGetValue(key, out value))
         throw new KeyNotFoundException();
      return value;
    }
}

Then you can define your keys like:

static readonly MyDictionaryKey<string> NameKey = new MyDictionaryKey<string>();
static readonly MyDictionaryKey<double> HeightKey = new MyDictionaryKey<double>();

and use it like

var myDict = new MyDictionary();
myDict.Add(NameKey, "Bill"); // this will take a string
myDict.Add(HeightKey , 1.2); // this will take a double

string name = myDict.Get(NameKey); // will return a string
double height = myDict.Get(HeightKey); // will return a double
Wilka
Thank you. As others have said, this is less of a practical than academic inquiry, but you hit the head on the nail in inferring that I wanted the key to determine the expected type of the item retrieved.
ProfK