Search code examples
c#genericsicollectionkeyvaluepair

Collection of key-value pairs where only key type is known


I want a collection class of key-value pairs, where ill know the key type at instantiation level but ill only know the value type when adding a new element to the collection.

Consider a the code snippet below

public class Collection<TKey> where TKey : class
{
    public ICollection<KeyValuePair<TKey, IValue>> Col { get; set; }

    public void Add<TValue>(TKey key, TValue value) where TValue : IValue
    {
        Col.Add(new KeyValuePair<TKey, IValue>(key, value));
    }
}

public interface IValue
{
}

This works well, however, the problem with the above code is that the insertion type must be of type IValue, since primitives aren't implementers of IValue they cannot be added to the list.

I cannot use object inplace of TValue / IValue

EDIT

I would like to use any! type for the value parameter of the key-value pair. If possible id like to get rid of IValue. It was the only way i could get the code to compile

An example of ideal usage is as follows:

    collection.Add("hello", 10);
    collection.Add("peter", "temp");
    collection.Add("hello1", new Foo());
    collection.Add("hello2", new Bar());

EDIT I cannot use object since object is not all objects are seriablisable, however, i changed the implementation to

class Program
{
    static void Main(string[] args)
    {
        var collection = new Collection<string>();
        collection.Add("hello", 10);
        collection.Add("peter", "temp");
        collection.Add("hello", new Bar());
    }
}

[Serializable]
public class KeyValuePair<TKey, TValue>
{
    private TKey _key;
    private TValue _value;

    public KeyValuePair(TKey key, TValue value)
    {
        _key = key;
        _value = value;
    }

    public TKey Key
    {
        get { return _key; }
        set { _key = value; }
    }

    public TValue Value
    {
        get { return _value; }
        set { _value = value; }
    }
}

public class Collection<TKey> where TKey : class
{
    public ICollection<KeyValuePair<TKey, ISerializable>> Col { get; set; }

    public void Add<TValue>(TKey key, TValue value) where TValue : ISerializable
    {
        Col.Add(new KeyValuePair<TKey, TValue>(key, value));
    }
}

The compiler says argument type <TKey, TValue> is not assignable to parameter type <TKey, ISerializable>


Solution

  • Note beforehand : As a personal preference I tend to use dictionary for key/value pairs with unique keys or multimap/ilookup when i need duplicate key inputs.


    If you use C# 3.5 or older you can use

    var dic = new Dictionary<string, object>();  
    

    Assuming you're on C# 4 you can use

    var dic = new Dictionary<string, dynamic>();  
    

    People like to use it to store JSON data for example.


    There is a lot what you can do with Rx-Linq, but instead I would like to note that you can write:

    var dic = new Dictionary<string, Lazy<string>>();
    

    where you can store a script that generates the string.