5

我正在尝试设置允许Object作为我的 TValue 的自定义 IDictionary。

这是它的样子:

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不能成为约束的额外功劳。

4

2 回答 2

7

这里的问题不在于泛型类型参数约束,而在于索引器的签名。

索引器被记录为始终返回 a TValue无论发生什么。然而else分支试图返回DependencyProperty.UnsetValue,它是 type object。由于并非所有objects 都是TValues,因此编译器会抱怨(“没有隐式转换”)。

如果您在 上放置任意数量的约束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使用 as 的值MissingValue?您可以将new()约束放在TValue静态构造函数上并在其中创建一个实例,但这会减少此类的可能应用程序。这导致设计开始使用起来有点笨拙,因为这正是你想要避免的,所以这样做没有多大意义。

于 2012-11-28T23:22:21.817 回答
5

为什么对象不能成为约束?我该如何解决这个问题?

你没有。你不需要。.NET 中的所有托管类型都可以转换为object. 有一些东西不能(非托管指针等),但无论如何它们与泛型不兼容。

我想,真正的问题DependencyProperty.UnsetValueobject。嗯……那不是TValue。想象一下TValueis intor byte:没有 or 的“未设置”intbyte。您不能object为这样的TValue.

坦率地说,我只是让你的调用者TryGetValue直接使用,而不是使用这个扩展方法。你可以做一些事情,比如用TValue, 或返回来返回一个虚拟类实例null- 但坦率地说,调用者可以更方便地调用TryGetValue来实现同样的事情。

于 2012-11-28T23:22:06.240 回答