为什么我不能有一个类型的对象约束

Vac*_*ano 5 .net c# generics

我正在尝试设置自定义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;
            }
        }        
    }
}
Run Code Online (Sandbox Code Playgroud)

当编译它时说:

无法将类型'object'隐式转换为'TValue'.

所以为了解决这个问题,我将类型约束更改为:

where TValue : object
Run Code Online (Sandbox Code Playgroud)

(object而不是上课)

然后我收到这条消息:

约束不能是特殊类'对象'

我该如何解决这个问题?

用于解释为什么object不能成为约束的额外功劳.

Jon*_*Jon 7

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

索引器被记录为始终返回a TValue,无论发生什么.else然而,分支尝试返回DependencyProperty.UnsetValue,这是类型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; }
}
Run Code Online (Sandbox Code Playgroud)

并从索引器返回,可能是因为它可以用于参考比较.

但这仍然会留下一个问题:如何实际获得一个TValue价值MissingValue?您可以将new()约束置于TValue静态构造函数中并在其中创建实例,但这会减少此类的可能应用程序.这导致设计开始变得有点笨拙使用,因为这正是你试图避免的那样,没有太多的意义.


Mar*_*ell 5

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

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

我猜,真正的问题DependencyProperty.UnsetValueobject.嗯......那不是TValue.想象一下TValue是:int或者byte没有"未设置"的值int或者byte.你不能object为这样的人返回任意的TValue.

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