Help using variance in C# 4.0
Question
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!
Solution
You could just define your Dictionary as private Dictionary<string, object>, and cast the objects before you return them from your Get method.
OTHER TIPS
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.
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.