我正在尝试设置自定义IDictionary,以允许Object
作为我的TValue。
这是它的样子:
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;
}
}
}
}
当编译它时说:
无法将类型'object'隐式转换为'TValue'。
所以为了解决这个问题,我改变了我的类型约束:
where TValue : object
(object
代替班级)
然后我收到这条消息:
约束不能是特殊类'对象'
如何解决这个问题?
解释为什么object
无法成为约束的额外信用。
答案 0 :(得分:7)
这里的问题不是泛型类型参数约束,而是索引器的签名。
索引器被记录为始终返回TValue
,恰好是的任何内容。但是,else
分支会尝试返回DependencyProperty.UnsetValue
,其类型为object
。由于并非所有object
都是TValue
s,编译器都会抱怨(“没有隐式转换”)。
如果您在TValue
上放置了任意数量的约束,即使您可以将其约束为object
,也没有区别。类型参数仍然可以设置为比object
更多的派生,DependencyProperty.UnsetValue
仍然无法转换为该类型。
如果您想达到这样的效果,可以使用public static
只读属性,例如
public class NullTolerantDictionary<TKey, TValue>
: Dictionary<TKey, TValue> where TValue : class
{
public static TValue MissingValue { get; private set; }
}
并从索引器返回,推测它可以用于参考比较。
但这仍然会留下一个问题:如何将TValue
值实际用作MissingValue
?您可以将new()
约束放在TValue
上并在静态构造函数中创建实例,但这会减少此类的可能应用程序。这导致设计开始变得有点笨拙使用,因为这正是你试图避免的那样,没有太大的意义。
答案 1 :(得分:5)
为什么对象不能成为约束?我该如何解决这个问题?
你没有。你不需要。 .NET中的所有托管类型都可以强制转换为object
。有些东西不能(非托管指针等),但它们与泛型不兼容。
我猜,真正的问题是DependencyProperty.UnsetValue
是object
。嗯....这不是TValue
。想象一下,TValue
为int
或byte
:int
或byte
没有“未设置”值。您无法为此类object
返回任意TValue
。
坦率地说,我只是让您的来电者直接使用TryGetValue
,而不是使用此扩展方法。你可能做一些事情,比如返回一个带有TValue
的虚拟类实例,或者返回null
- 但坦率地说,调用者可以只调用TryGetValue
更方便地实现同样的目的。