I want to declare a dictionary that stores typed IEnumerable
\'s of a specific type, with that exact type as key, like so: (Edited to follow johny g\'s comment)<
class WeirdDictionary : IDictionary
, that will overload the Add method to take a Type and an IEnumerable of that type, which you can do using constraints, and cast the IEnumerable<> to IEnumerable. Overload the indexer aswell, and cast it back to the relevant type.IEnumerable
being as good as IEnumerable
(This is called variance, I believe?)This solution is slightly generalized, since reuse rocks
Edit by 280Z28:
At first I marked this down because point #2 was confusing and I misinterpreted it. By using explicit implementation of methods in IDictionary
and providing generic alternatives, you can get a pretty clean interface. Note that you cannot create generic indexers, so you'll have to always use TryGet
(which is a good idea anyway). I only included explicit implementation of one of the IDictionary<>
methods to show how to perform the checks. Do not derive WeirdDictionary
directly from Dictionary
or you will lose the ability to guarantee constraints in the underlying data.
class WeirdDictionary : IDictionary
{
private readonly Dictionary _data =
new Dictionary();
public void Add(IEnumerable value)
{
_data.Add(typeof(T), value);
}
public bool TryGet(out IEnumerable value)
{
IEnumerable enumerable;
if (_data.TryGetValue(typeof(T), out enumerable)
{
value = (IEnumerable)enumerable;
return true;
}
value = null;
return false;
}
// use explicit implementation to discourage use of this method since
// the manual type checking is much slower that the generic version above
void IDictionary.Add(Type key, IEnumerable value)
{
if (key == null)
throw new ArgumentNullException("key");
if (value != null && !typeof(IEnumerable<>).MakeGenericType(key).IsAssignableFrom(value.GetType()))
throw new ArgumentException(string.Format("'value' does not implement IEnumerable<{0}>", key));
_data.Add(key, value);
}
}
End 280Z28