I am trying to setup custom IDictionary that will allow Object as my TValue.
Here is what it looks like:
public class NullTolerantDictionary<TKey, TValue>
: Dictionary<TKey, TValue> where TValue : class
{
public TValue this[TKey key]
{
get
{
TValue value;
if (TryGetValue(key, out value))
{
return value;
}
else
{
return DependencyProperty.UnsetValue;
}
}
}
}
When this compiles it says:
Cannot implicitly convert type ‘object’ to ‘TValue’.
So to fix this I change my type constraint to be like this:
where TValue : object
(object instead of class)
I then get this message:
Constraint cannot be special class ‘object’
How do I get around this?
Extra credit for explaining why object is not able to be a constraint.
The problem here is not with generic type argument constraints but with the signature of the indexer.
The indexer is documented to always return a
TValue, whatever that happens to be. Theelsebranch however tries to returnDependencyProperty.UnsetValue, which is of typeobject. Since not allobjects areTValues, the compiler complaints (“no implicit conversion”).It would make no difference if you placed any number of constraints on
TValue, and even if you could constrain it toobject. The type argument could still be set to anything more derived thanobjectandDependencyProperty.UnsetValuewould still not be convertible to that type.If you want to achieve such an effect you could use a
public staticread-only property such asand return that from the indexer, presumably so that it can then be used in reference comparisons.
But that would still leave open the question: how do actually get a
TValuevalue to use asMissingValue? You could place thenew()constraint onTValueand create an instance inside a static constructor, but that would decrease the possible applications for this class. This results in the design starting to get a bit clunky to use, and since that’s exactly what you are trying to avoid there’s not much point in going that way.