【问题标题】:IComparable in C#C# 中的 IComparable
【发布时间】:2013-08-06 05:31:20
【问题描述】:

我有一个名为 Shape 的对象,其中包含一个 public int[,] coordinate { get; set; } 字段。

我有一个单独的类,其中包含 Shape 对象的集合。在某个特定点,我希望检查:

if(shapes.Contains(shape))
{
   // DoSomething
}

所以在Shape 类中我添加了IComparable 引用并插入了CompareTo 方法:

public int CompareTo(Shape other)
{
    return this.coordinate.Equals(other.coordinate);
}

然而我得到一个错误:

Cannot implicitly convert type 'bool' to 'int'

因此,我该如何表述 return 以使其返回 int 而不是 bool,因为它目前正在这样做?

更新

如果我将返回码更改为:

return this.coordinate.CompareTo(other.coordinate);

我收到以下错误消息:

错误 1“ShapeD.Game_Objects.Shape”未实现接口成员“System.IComparable.CompareTo(ShapeD.Game_Objects.Shape)”。 “ShapeD.Game_Objects.Shape.CompareTo(ShapeD.Game_Objects.Shape)”无法实现“System.IComparable.CompareTo(ShapeD.Game_Objects.Shape)”,因为它没有匹配的返回类型“int”。 C:\Users\Usmaan\Documents\Visual Studio 2012\Projects\ShapeD\ShapeD\ShapeD\Game Objects\Shape.cs 10 18 ShapeD

【问题讨论】:

  • 新的错误信息很容易解决,将 public int CompareTo(Shape other) 更改为 public int CompareTo(object other) 但随后您将面临转换问题,并且对于多维数组不存在 CompareTo。

标签: c# comparison compare icomparable


【解决方案1】:

IComparable 意味着,两个对象可以在某种意义上进行比较,您可以判断哪个对象具有“更高的价值”。它通常用于排序目的。您应该改写Equals 方法。您还应该使用Point 结构而不是数组。

class Shape : IEquatable<Shape>
{
    public Point coordinate { get; set; }

    public bool Equals(Shape other)
    {
        if (other == null) return false;
        return coordinate.Equals(other.coordinate);
    }

    public override bool Equals(object other)
    {
        if (other == null) return false;
        if (ReferenceEquals(this, other)) return true;
        var shape = other as Shape;
        return Equals(shape);
    }

    public override int GetHashCode()
    {
        return coordinate.GetHashCode()
    }
}

【讨论】:

  • @Subby @Nikita 这些EqualsGetHashCode 实现似乎是错误的。你的坐标是一个多维数组,你可能不想将你的平等基于ReferenceEquals
  • @ErenErsönmez,在我的示例中没有多维数组。在我看来,OP 正在使用它来简单地设置单点的 x 和 y 坐标,所以我用Point struct 替换它。我也没有看到使用ReferenceEquals 的问题。我错过了什么吗?
  • @NikitaBrizhak OP 需要一个多维数组(参见问题中的第一句)。对于值类型和数组,ReferenceEquals 很少 有意义。最有可能的是,您希望根据数组内的值进行比较(而不是基于指向完全相同的数组实例的两个引用)。
  • @ErenErsönmez,我说的是intent。如果目的是存储单个坐标值(单词coordinate,单数形式,使我得出这个结论),那么使用数组根本没有意义,正如我在示例中指出的那样。如果目的是存储一些路径几何图形,那么coordinate 应该是IList&lt;Point&gt; 或其他一些可能专用的集合。无论哪种方式,使用多维数组存储坐标对我来说都是错误的,这就是我的观点。至于ReferenceEquals,这是有道理的,因为它比较了对Shape 对象的两个引用,而不是数组。
【解决方案2】:

由于您只想检查是否相等,请实现 IEquatable 接口 not IComparableIComparable 用于排序目的

public bool Equals(Shape s)
{

    int count=0;
    int[] temp1=new int[this.coordinate.Length];
    foreach(int x in this.coordinate)temp1[count++]=x;//convert to single dimention

    count=0;
    int[] temp2=new int[s.coordinate.Length];
    foreach(int x in s.coordinate)temp2[count++]=x;//convert to single dimention

    return temp1.SequenceEqual(temp2);//check if they are equal

}

注意

IEquatable 应该为可能存储在 generic 集合中的任何对象实现 else 您还必须覆盖 Object 的 Equals 方法。也正如在其他 ans 使用中指出的那样Point struct 而不是多维数组

【讨论】:

    【解决方案3】:

    要执行包含检查,您需要覆盖 Shape 类中的 Equals 运算符。

    【讨论】:

      【解决方案4】:

      复活一个老问题只是因为它仍然会导致谷歌点击,尽管一些答案非常糟糕。 您不应该使用 CompareTo 或 Equals。 这些都不适合您尝试做的事情,只会引起混乱,正如此处所写的答案所证明的那样。 编写您自己的方法,称为 IntersectsWith。 看看任何像样的几何库(例如,如果你很高兴从 c++ 中提取出来,则提升)作为如何去做。 至于从 bool 到 int 的转换,这可以通过使用带有 ? 的 bool 轻松完成。三元运算符。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-23
        • 1970-01-01
        相关资源
        最近更新 更多