代码之家  ›  专栏  ›  技术社区  ›  Wei Lin

C new dictionary<string,object>()is idictionary<object,object>return false

c#
  •  2
  • Wei Lin  · 技术社区  · 6 年前

    例子:

    void Main()
    {
        var dic = new Dictionary<string, object>();
    
        Console.WriteLine(dic is IDictionary<object, object>); //False
        Console.WriteLine(dic is IDictionary<dynamic, dynamic>); //False
        Console.WriteLine(dic is IDictionary<string, object>); //True
    }
    

    字符串不是一个对象吗?为什么? dic is IDictionary<object, object> 弄虚作假。

    2 回复  |  直到 6 年前
        1
  •  2
  •   Mrinal Kamboj    6 年前

    总结

    除了理解 Covariance-Contravariance 从发布的适用于接口和委托的链接中,让我们更详细地了解这个问题,下面是 Dictionary<TKey,TValue> 它实现了 IDictionary<TKey,TValue> ,其中两种类型 Tkey TValue 都是不变的,既不只是协变的,也不只是反变的,这意味着它们都可以在输入和输出位置,这取决于方法或属性,当然类型兼容性在实现这些方法/属性时是很重要的。

    假设以下是有效代码:

    Dictionary<string,object> : IDictionary<object,object> ,那么它的意思是:

    仅考虑 TKey 因为这是唯一不同的,在相反的位置 in ,像 bool ContainsKey(TKey key); ,您正在提供 string 但它正在接受 object 很好,因为 对象 是基类,但协变位置 out 会有麻烦的,比如 ICollection<TKey> Keys {get;} 因为你愿意归还 对象 .NET C中的所有内容都可以类型化为 对象 类型,但调用方只要求 一串 .

    上面的代码甚至不会编译

    Dictionary 上面的代码甚至不会编译,你的困惑是从这个角度来看,如果我可以分配一个 一串 类型转换为 对象 打字,那为什么不呢 Dictionary<string,object> IDictionary<object,object> ,只是因为 词典 它本身是一个开放的泛型类型实现,当类型在使用前被分配时关闭,这里的映射用于 词典 类型,它本身可以分配给 对象 基类不适用于用于创建封闭数据结构的单个类型,因此匹配它们以确保在任何位置具有类型的所有方法都可以无缝工作是很重要的。

    有趣的案例 IEnumerable<out T>

    事实上, IEnumerable<out T> 是个有趣的例子,它有协变 type T ,这是.NET中所有集合的基本接口,在这里我们可以 List<ChildClass> 提供给 IEnumerable<Baseclass> ,因为 Baseclass 只在输出位置,所以可以接受任何子类对象,事实上这种不兼容性是引入协方差和逆变的原因之一,否则就不可能使用不符合开发人员期望的不变类型进行赋值。

    查看代码段以了解区别:

    void Main()
    {
        var list = new List<string>();
    
        var dictionary = new Dictionary<string,object>();
    
        var isTrue = list is IEnumerable<object>;
    
        isTrue.Print(); // Prints True
    
        isTrue = dictionary is IDictionary<object,object>;
    
        isTrue.Print(); // Prints False
    
        isTrue = dictionary is IEnumerable<KeyValuePair<object,object>>;
    
        isTrue.Print(); // Prints False, KeyValuePair<string,object> is not same 
      //as KeyValuePair<object,object>, there's no default compatibility
    
        isTrue = dictionary is IEnumerable<KeyValuePair<string, object>>;
    
        isTrue.Print(); // Prints True
    }
    
        2
  •  6
  •   dee-see Tom Ritsema    6 年前

    String 源自一个 Object . 但是 IDictionary<string, object> 不是从 IDictionary<object, object> .这就是它返回错误的原因。你可能想了解一下.NET中的协方差和反方差概念。 https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance