【问题标题】:IComparable<T>.CompareTo() return values?IComparable<T>.CompareTo() 返回值?
【发布时间】:2015-06-28 20:28:36
【问题描述】:

只是一个关于IComparable&lt;T&gt;.CompareTo() 方法的奇怪问题;我知道该方法需要根据比较返回正数、负数或零,但我在前两种情况下返回的结果真的很重要吗?换句话说,如果我返回 +1 或 +1000 会有什么不同吗?

【问题讨论】:

  • No.. 1、10、100、1000 是一样的。唯一重要的是符号(或 0)。我建议不要将 int.MinValue 作为显式值返回。
  • @xanatos - 这真是个糟糕的建议。特别是当结果的一些创造性使用使用乘法时。这会导致溢出。单击来自@siride 的链接并注意return 1;
  • @HenkHolterman 任何将CompareTo 的结果相乘的人都应该得到发生在他/她身上的任何事情。或者甚至增加了它。那么,如果你想参加“混淆 C# 竞赛”,那就是另一个问题了。
  • @HenkHolterman 只是出于好奇...((byte)255).CompareTo((byte)1) == 254 on .NET 4.5(似乎与sbyte、short、ushort、char 相同)跨度>

标签: c#


【解决方案1】:

答案是:

IComparable&lt;T&gt;.CompareTo() 为 sbyte, short, ushort, char 类型返回 减法结果,同时返回 -1,0 或 1 用于int、long、string 等类型。

var result = ((byte)10).CompareTo((byte)2); // 8
var result = ((short)1).CompareTo((byte)11); // -10
var result = ((int)10).CompareTo((int)11); // 1 ??

原因:

首先我们看一下方法的签名:

int CompareTo(T other)

如您所见,返回类型为Int32。

很明显,开发人员希望返回值的差异。 但是,Int32 减法的返回类型可以小于Int32.MinValue 或大于Int32.MaxValue。 例如,让我们来看看:

// Return type is less than minimum int value  (-4294967296)
(Int32.MinValue).CompareTo(Int32.MaxValue) 

 // Return type is greater than maximum int value (4294967296)
(Int32.MaxValue).CompareTo(Int32.MinValue)

因此,他们决定为具有“小”值范围的类型返回减法结果,而不是在这种情况下为 Int32 的方法的返回类型。

最后,你可以从here查看该方法在所有类型中的实现:

Here is the Int16 implementation:

   public int CompareTo(Int16 value) {
            return m_value - value;
        }

Here is the Int32 implementation:

public int CompareTo(int value) {
            // Need to use compare because subtraction will wrap
            // to positive for very large neg numbers, etc.
            if (m_value < value) return -1;
            if (m_value > value) return 1;
            return 0;
        }

最后:

但是,当然,将来他们可以更改该代码的实现,推荐的方法是始终按照 msdn 中的说明将结果与 1、0 或 -1 进行比较。

小于零(此实例在排序顺序中位于其他实例之前。)
零(此实例在排序顺序中的位置与 other 相同。)
大于零(此实例在排序顺序中位于 other 之后。)

【讨论】:

  • 这只是当前的实现。明智的做法是不要依赖 Compare 的任何特定返回值(0 除外)。
  • @HenkHolterman 我完全同意你的看法。但是,这个结果的原因对我来说很有趣,我认为对其他人来说可能很有趣。所以,我添加了原因作为答案。
【解决方案2】:

如果我返回 +1 或 +1000 会有什么不同吗?

不应该。但谨慎表示最好是双向安全:

  • 总是返回 -1、0、+1
  • 始终使用&lt; 0, &gt; 0

【讨论】:

  • 根据我的经验,在许多情况下,CompareTo 委托给另一个 CompareTo,而另一个 CompareTo 作为 .NET Framework 的一部分提供,并且可以返回非 -1 的值, 0 和 1。我当然不会推荐像 int CompareTo(MyObject other) { int result = Id.CompareTo(other.Id); if (result &lt; 0) return -1; if (result &gt; 0) return 1; return 0; } 这样的东西而不是 int CompareTo(MyObject other) { return Id.CompareTo(other.Id); }。 (假设通过查看 Id 属性来比较 MyObjects 是有意义的。)我读到你的回答是推荐前者。对吗?
  • 当它是一个直接的链接时,我不会写 if()s ,但规则 1 适用于你发起或组合任何结果。
  • 即使合并结果,我也宁愿写成int CompareTo(MyObject other) { int result = A.CompareTo(other.A); if (result == 0) result = B.CompareTo(other.B); if (result == 0) result = C.CompareTo(other.C); return result; } 之类的东西,它不能保证返回-1、0、+1。如果您以不同的方式编写它是完全有效的,但我并没有真正看到返回其他值有什么问题,我不知道如何保持重写版本同样可读,所以我不太明白你的建议在那里。
  • 感谢您的回答!我想我的下一个问题是,返回结果在排序过程中是如何实际使用的?
  • @WaiHaLee 公平点,我也不推荐int CompareTo(MyObject other) { return Math.Sign(Id.CompareTo(other.Id)); } 而不是int CompareTo(MyObject other) { return Id.CompareTo(other.Id); }。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-23
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多