首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IComparable接口约束

IComparable接口约束
EN

Stack Overflow用户
提问于 2009-05-27 16:52:46
回答 5查看 2.3K关注 0票数 11

当我想要约束类型T是可比较的时,我应该使用:

代码语言:javascript
复制
where T : IComparable

代码语言:javascript
复制
where T : IComparable<T>

如果#2有意义,我就不能理解了。有谁能解释一下会有什么不同?

EN

回答 5

Stack Overflow用户

发布于 2009-05-27 17:03:39

IComparable和IComparable<>之间的主要区别是,第一个是预泛型,因此允许您对任何对象调用compare方法,而第二个强制它共享相同的类型:

代码语言:javascript
复制
IComparable - CompareTo(object other);
IComparable<T> - CompareTo(T other);

如果您不打算使用任何旧的.net 1.0库,而这些库的类型可能没有实现现代的泛型解决方案,那么我会选择第二种方法。您将获得性能提升,因为您将避免拳击,比较将不需要检查类型匹配,您还将获得温暖的感觉,来自最先进的方式做事情…

为了解决Jeff的非常好和中肯的观点,我认为在泛型上放置尽可能少的约束来执行任务是一种好的实践。由于您可以完全控制泛型中的代码,因此您可以知道是否正在使用需要基本IComparable类型的任何方法。因此,考虑到他的评论,我个人将遵循以下规则:

  • 如果您不希望泛型使用任何仅实现IComparable的类型(即遗留1.0代码),并且您没有从依赖于IComparable参数的泛型内部调用任何方法,则只使用IComparable<>约束。
  • 如果您正在使用仅实现IComparable的类型,则仅使用该约束
  • 如果您正在使用需要IComparable参数的方法,而不是使用仅实现IComparable的类型,则在使用接受泛型类型的方法时,使用杰夫的答案中的两个约束将提高性能。

为了扩展第三条规则,让我们假设您正在编写的类如下所示:

代码语言:javascript
复制
public class StrangeExample<T> where ... //to be decided
{
    public void SortArray(T[] input)
    {
         Array.Sort(input);
    }

    public bool AreEqual(T a, T b)
    {
        return a.CompareTo(b) == 0;
    }
}

我们需要决定对它施加什么约束。SortArray方法调用Array.Sort,这需要传入的数组来包含实现IComparable的对象。因此,我们必须有一个IComparable约束:

代码语言:javascript
复制
public class StrangeExample<T> where T : IComparable

现在该类将被正确编译和工作,因为T的数组对于Array.Sort是有效的,并且在接口中定义了一个有效的.CompareTo方法。但是,如果您确定不希望将类与未同时实现IComparable<>接口的类型一起使用,则可以将约束扩展为:

代码语言:javascript
复制
public class StrangeExample<T> where T : IComparable, IComparable<T>

这意味着当调用AreEqual时,它将使用更快的泛型CompareTo方法,您将看到性能上的好处,但代价是不能与旧的.NET 1.0类型一起使用。

另一方面,如果您没有AreEqual方法,那么IComparable<>约束就没有任何好处,所以您也可以放弃它--不管怎样,您只使用IComparable实现。

票数 6
EN

Stack Overflow用户

发布于 2009-05-27 17:21:26

您可能需要这两个约束,如下所示:

代码语言:javascript
复制
where T : IComparable, IComparable<T>

这将使您的类型与更多的IComparable接口用户兼容。当T是值类型时,IComparable的泛型版本IComparable将有助于避免装箱,并允许更强类型的接口方法实现。支持两者都可以确保无论其他对象请求哪个接口,您的对象都可以遵守,因此可以很好地进行互操作。

例如,Array.SortArrayList.Sort使用IComparable,而不是IComparable

票数 6
EN

Stack Overflow用户

发布于 2009-05-27 17:02:38

IComparable<T>允许比较器是强类型的。

你可以拥有

代码语言:javascript
复制
public int CompareTo(MyType other)
{
    // logic
}

与之相对

代码语言:javascript
复制
public int CompareTo(object other)
{
    if (other is MyType)
        // logic
}

以下面的示例为例,它实现了这两个接口:

代码语言:javascript
复制
public class MyType : IComparable<MyType>, IComparable
{
    public MyType(string name, int id)
    { Name = name; Id = id; }

    public string Name { get; set; }
    public int Id { get; set; }

    public int CompareTo(MyType other)
    {
        if (null == other)
            throw new ArgumentNullException("other");
        return (Id - other.Id > 0 ? 1 : 0);
    }

    public int CompareTo(object other)
    {
        if (null == other)
            throw new ArgumentNullException("other");
        if (other is MyType)
            return (Id - (other as MyType).Id > 0 ? 1 : 0);
        else
            throw new InvalidOperationException("Bad type");
    }
}


MyType t1 = new MyType("a", 1);
MyType t2 = new MyType("b", 2);
object someObj = new object();

// calls the strongly typed method: CompareTo(MyType other)
t1.CompareTo(t2);
// calls the *weakly* typed method: CompareTo(object other)
t1.CompareTo(someObj);

如果MyType只用IComparable<MyType>实现,那么第二个compareTo(someObj)就是一个编译时错误。这是强类型泛型的一个优点。

另一方面,框架中有一些方法需要非泛型IComparable,比如Array.Sort。在这些情况下,您应该考虑实现这两个接口,如本例所示。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/916852

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档