I have a class like the following:
public class DropDownControl<T, Key, Value> : BaseControl
where Key: IComparable
{
private IEnumerable<T> mEnumerator;
private Func<T, Key> mGetKey;
private Func<T, Value> mGetValue;
private Func<Key, bool> mIsKeyInCollection;
public DropDownControl(string name, IEnumerable<T> enumerator, Func<T, Key> getKey, Func<T, Value> getValue, Func<Key, bool> isKeyInCollection)
: base(name)
{
mEnumerator = enumerator;
mGetKey = getKey;
mGetValue = getValue;
mIsKeyInCollection = isKeyInCollection;
}
And I want to add a convenience function for Dictionaries (because they support all operations efficiently on their own).
But the problem is that such a constructor would only specify Key and Value but not T directly, but T is just KeyValuePair. Is there a way to tell the compiler for this constructor T is KeyValuePair, like:
public DropDownControl<KeyValuePair<Key, Value>>(string name, IDictionary<Key, Value> dict) { ... }
Currently I use a static Create function as workaround, but I would like a direct constructor better.
public static DropDownControl<KeyValuePair<DKey, DValue>, DKey, DValue> Create<DKey, DValue>(string name, IDictionary<DKey, DValue> dictionary)
where DKey: IComparable
{
return new DropDownControl<KeyValuePair<DKey, DValue>, DKey, DValue>(name, dictionary, kvp => kvp.Key, kvp => kvp.Value, key => dictionary.ContainsKey(key));
}
No, basically. The static method in a non-generic class (such as DropDownControl [no <>]) is the best approach, as you should be able to use type-inference when you call Create() - i.e.
var control = DropDownControl.Create(name, dictionary);
C# 3.0 helps here both via "var" (very welcome here) and by the much-improved generic type inference rules. In some (more general) case, another similar option is an extension method, but an extension method to create a very specific control from a dictionary doesn't feel very natural - I'd use a non-extension method.
Something like:
public static class DropDownControl
{
public static DropDownControl<KeyValuePair<TKey,TValue>, TKey, TValue>
Create<TKey,TValue>(IDictionary<TKey, TValue> value, string name)
where TKey : IComparable
{
return new DropDownControl<KeyValuePair<TKey, TValue>, TKey, TValue>
(name, value, pair => pair.Key, pair => pair.Value,
key => value.ContainsKey(key)
);
}
}
Another option is inheritance, but I don't like it much...
public class DropDownControl<TKey, TValue> :
DropDownControl<KeyValuePair<TKey, TValue>, TKey, TValue>
where TKey : IComparable
{
public DropDownControl(IDictionary<TKey, TValue> lookup, string name)
: base(name, lookup, pair => pair.Key, pair => pair.Value,
key => lookup.ContainsKey(key)) { }
}
This adds complexity and reduces your flexibility... I wouldn't do this...
Overall, it sounds like you want to be working with just IDictionary<,> - I wonder if you can't simplify your control to just use this, and force non-dictionary callers to wrap themselves in an IDictionary<,> facade?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With