Collection of a type with generic parameters

Hey guys, I am trying to make a Variable collection which will be loaded/saved and also changeable through a debug console. I’m having a design issue. I am creating a type called Variable, where T is the type of value stored, such as float or int. The constructor would be something like (string name, T defaultValue).

This is all good so far. The problem is storing these Variable objects. I’d like the variables to be accessible with a string key (like a Hashtable), but I am unsure of how to make a Dictionary of a generic type :S.

I’d like to avoid casting and such if possible, as I’d like this to have good performance. I’d imagine getting variables with a piece of code like this: variableCollection.GetValue(“Sensitivity”) or something of the sort.

I’m not asking for anyone to make it for me, just hoping to be pointed in the right direction. Thanks!

Right, I understand that. But my Variable type is Variable. I can’t make a Dictionary<string,Variable> :\

What you’re actually asking for, though you may not know the terminology, is the construction of an Unbounded generic type. That’s something that .net can’t do (horrible enum hacks aside).

Generics have very specific rules about what gets defined where, and all of them require concrete types when you create an instance. There’s no way to do this without resorting to casting, or the painfully slow dark arts of reflection.

Edited to add:
Performance of this sort of thing shouldn’t be too awfully bad, though it’s not very safe:

public class KeyValueStore<TKey>
    {
        private readonly Dictionary<TKey, object> _data = new Dictionary<TKey, object>();

        public Variable<TValue> GetValue<TValue>(TKey key)
        {
            return (Variable<TValue>) _data[key];
        }
    }
1 Like

Hmm I just feel there is a clean way to do this and it’s just beyond my reach…

I may be able to adapt your solution and add some type safety checks. In the meantime, if anyone has any good ideas, please share :).

Thanks for the help, everyone!

After sleeping on it, best I could come up with was if you limit what types your Variable uses, you could probably pull this sort of thing off:

public class KeyValueStore<TKey>
{
    private Dictionary<TKey, Variable<int>> _intDict = new Dictionary<TKey, Variable<int>>();
    private Dictionary<TKey, Variable<float>> _floatDict = new Dictionary<TKey, Variable<float>>();

    public Variable<int> GetInt(TKey key)
    {
        return _intDict[key];
    }

    public Variable<float> GetFloat(TKey key)
    {
        return _floatDict[key];
    }
}

You’re also setting yourself up for a huge performance nightmare. Here’s what you could do:

public interface IVariable
{
   public Type ObjectType { get; }  
}

then:

public class Variable<T> : IVariable
{
    public Type ObjectType { get { return typeof(T); } }
    public string Key { get; set; }
    public T Value

    public Variable(string key, T value)
    {

     }
}

Then in your Dictionary make it: Dictionary<string, IVariable>

Now here’s the problem… how are you going to get that value? You could create a GetValue method in your interface but return type would have to be “object”, then you cast the return value to whatever type is stored in ObjectType. Easy enough but here’s the kicker:

#1 - Variable is a bad thing… because T might be int, string, whatever. So now you’re creating a reference type to hold a value type and you’re creating an allocation every time you do this. Of course you can make Variable a struct which would avoid that issue… but you’re still going to run into Issue #2 below

#2 - The only way you’ll be able to get the type is to call GetType which returns an object, then cast it to whatever the type actually is (which could be int, string, whatever). In this case you’re boxing / unboxing and you’re allocating anyway and feeding the GC monster.

So… what you’re trying to do is probably a bad idea. Try to think of a better solution.

Funny, I actually already almost completed it with this same design, although I used an abstract class instead of an interface.

Hmm… maybe instead of GetVariable returning a value of type T, it could return a Variable (after confirming that the types match), and then whatever object called GetVariable would just cache the Variable and be able to access a current value any time. Kind of messy :, not sure if I want that.

Thanks for the advice, guys!