【问题标题】:Why doesn't IComparable<T> inherit from IComparable?为什么 IComparable<T> 不从 IComparable 继承?
【发布时间】:2020-01-23 16:27:06
【问题描述】:

在大多数地方,我读到最好从类中的IComparableIComparable&lt;T&gt; 继承以提供与非泛型集合的兼容性。我的问题是为什么IComparable&lt;T&gt; 默认不从IComparable 继承呢?向后兼容性将通过这种方式实现。

例如,IEnumerable&lt;T&gt; 确实继承自 IEnumerable,那么为什么不对 IComparable 做同样的事情呢?我阅读了有关差异的信息,但我仍然不明白为什么它是这样设计的。我尝试使用具有相同架构的接口创建一个小示例,并且它按预期工作。

编辑: 此外,Microsoft 文档指出以下内容: 如果泛型接口是逆变的,则泛型接口可以从非泛型接口继承,这意味着它只使用其类型参数作为返回值。在 .NET Framework 类库中,IEnumerable&lt;T&gt; 继承自IEnumerable,因为IEnumerable&lt;T&gt; 仅在GetEnumerator 的返回值和Current 属性getter 中使用了T。

但尽管如此,一个人可以从IComparable&lt;T&gt; 继承IComparable 就好了(如果你创建具有相同架构的接口,那就是)。

【问题讨论】:

标签: c# interface comparable contravariance icomparable


【解决方案1】:

如果没有指定类型,请自行尝试,那么实现泛型接口的类也需要实现默认类型方法

    public interface IFoo
    {
        void Foo(object o);
    }

    public interface IFoo<T> : IFoo
    {
        void Foo(T o);
    }

变成了

public class Foo : IFoo<int>
    {
        void IFoo<int>.Foo(int o)
        {
            throw new System.NotImplementedException();
        }

        void IFoo.Foo(object o)
        {
            throw new System.NotImplementedException();
        }
    }

在这种情况下,您使用一种方法实现一个接口,并且您似乎必须实现两个从类型化接口继承的方法

【讨论】:

  • 那么,主要的问题是,你应该实现两种方法而不是仅仅实现一种具有这种继承性的方法并不明显?
  • 类 Foo : IFoo 怎么样?
【解决方案2】:

这归结为语言设计决策,开发者的单词太少了,我们只能猜测。

一个很好的理由当然是一个是通用的,另一个不是。泛型本质上优于非泛型解决方案(这意味着使用对象作为类型),因为它们在编译时保持类型安全。因此,可能有一个有意的选择来打破前通用版本。避免向下兼容。请注意大多数实现通用版本的类如何不实现它的非通用版本。像字符串这样真正基础的和旧的东西是例外 - 因为它们无法删除旧接口,只能添加新接口。

对于枚举器,需求似乎不那么极端。枚举器通常是从一个集合中生成的,而不是从一个集合中生成的,然后是纯粹的读取处理。所以你要么有一个固定类型要转换,要么有一个固定类型要在枚举器中使用。

另一个原因可能是使用 IComparable 的代码要么明确要求它(类型约束),要么包含由它制成的东西——并且根据定义本身就是通用的。大多数情况下,它用于 generic 集合中的排序功能。他们可能不想再使用旧的收藏了。并且不支持 Dictionary 上的 IComparable 无疑是让 HashTable(它的前通用对应物)退出流通的好选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 2016-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多