tags:

views:

261

answers:

3

Here's the problem. I would like to create a class which will contain configuration data. This data consists of key/value pairs. Some examples: "hostName"="localhost", "timeout"=1000, etc.. My initial idea was to store all these in a generic dictionary:

private Dictionary<string, ConfigurationItem<object>> Configuration = 
    new Dictionary<string, ConfigurationItem<object>>();

And the ConfigurationItem class as:

public class ConfigurationItem<T>
{
    public string Name { get; set; }
    public T Value { get; set; }
}

My hopes are that I can query and set the configuration as follows:

int i = Configuration.Get<int>("Timeout");
Configuration.Set("Timeout", 1000);

Unfortunately, I can't insert items in the configuration dictionary using the following code:

public void SetValue<T>(string key, ConfigurationItem<T> value)
{
        if (Configuration.ContainsKey(key.ToUpper()))
            Configuration[key.ToUpper()] = **value**;
        else
            Configuration.Add(key.ToUpper(),  **value**);
}

The bold parts are showing errors:

Cannot convert type ConfigurationItem<T> to ConfigurationItem<Object>

I am using C# 4.0 since I hoped to fixed this problem using the new variance feature, but no luck so far. If more information is needed, just name it! Thanks for your help!

+2  A: 

Covariance and contravariance in C# 4.0 only applies to interfaces and delegates.

You must prefix the type parameter with in or out, depending upon the location of usages of the type parameter in the interface member's definitions.

For example:

public interface IConfigurationItem<out T>
{
    public string Name { get; set; }
    public T Value { get; set; }
}

Because IDictionary<TKey,TValue> uses both its type parameters for inputs and outputs, dictionary are not covariant or contravariant.

Drew Noakes
Thanks Eric. Right you are.
Drew Noakes
+1  A: 

From C# 4.0 draft specification variance limitations

23.3 Limitations Co- and contravariant type parameters can only be declared on interfaces and delegate types. Co- and contravariance only applies when there is a reference (or identity) conversion between the type arguments. For instance, an IEnumerable<int> is not an IEnumerable<object> because the conversion from int to object is a boxing conversion, not a reference conversion.

Dzmitry Huba
A: 

You could just define your Dictionary as private Dictionary<string, object>, and cast the objects before you return them from your Get method.

Lance Fisher
Thanks Lance, thats what I'll do then, though I was looking for a solution that did not require any explicit casting.
Dominiek