c# - 为什么 SByte 和 Int32 CompareTo() 方法的行为不同?

标签 c# .net

如果你运行下面的代码:

SByte w = -5;
Console.WriteLine(w.CompareTo(0));

Int32 x = -5;
Console.WriteLine(x.CompareTo(0));

SByte y = 5;
Console.WriteLine(y.CompareTo(0));

Int32 z = 5;
Console.WriteLine(z.CompareTo(0));

然后你得到以下输出:

-5
-1
5
1

为什么这些在 MSDN 文档中具有几乎相同描述的同名方法的行为如此不同?

最佳答案

因为 SByte.CompareTo()

一样实现
return m_value - value;

所以一个简单的减法。这是有效的,因为 m_value 会自动转换为 int,并且任何可能的值组合对于 int 都是“合法的”。

有两个Int32这是无法完成的,因为例如 Int32.MinValue.CompareTo(Int32.MaxValue) 会变成 Int32.MinValue - Int32.MaxValue 会在 int 范围,实际上它被实现为两个比较:

if (m_value < value) return -1;
if (m_value > value) return 1;
return 0;

一般

CompareTo 的返回值唯一重要的“事情”是它的符号(或者如果它是 0)。 “值(value)”是无关紧要的。 CompareTo()的1、5、500、5000、5000000的返回值是一样的。 CompareTo 不能用于测量数字之间的“距离”。所以这两种实现是等价的。

这样做完全是错误的:

if (someValue.CompareTo(someOtherValue) == -1)

你必须永远

if (someValue.CompareTo(someOtherValue) < 0)

为什么 SByte.CompareTo 是这样构建的

SByte.CompareTo 正在实现“无分支”比较(代码中没有 if,代码流是线性的)。处理器有分支问题,因此无分支代码可能比“分支”代码更快,所以这个微优化。显然 SByte.CompareTo 可以写成 Int32.CompareTo

为什么任何负值都等于 -1(而任何正值都等于 +1)

这可能是直接从 C 语言派生出来的东西:qsort例如比较项目的函数使用用户定义的方法,如下所示:

Pointer to a function that compares two elements.
This function is called repeatedly by qsort to compare two elements. It shall follow the following prototype:

int compar (const void* p1, const void* p2);

Taking two pointers as arguments (both converted to const void*). The function defines the order of the elements by returning (in a stable and transitive manner):
return value meaning
<0 The element pointed to by p1 goes before the element pointed to by p2
0 The element pointed to by p1 is equivalent to the element pointed to by p2
>0 The element pointed to by p1 goes after the element pointed to by p2

.CompareTo 在其他原始类型中是如何实现的?

SByte , Byte , Int16 , UInt16 , Char都是用减法“法”,而Int32 , UInt32 , Int64 , UInt64全部使用 if“方法”。

关于c# - 为什么 SByte 和 Int32 CompareTo() 方法的行为不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36426429/

相关文章:

c# - 如何从 XAML 中的 DataTemplate 引用匹配对象?

c# - 如何使用 .NET 获取属性中的构造函数参数名称?

.net - 查找 LINQ 提供程序支持的方法

c# - 无法将参数值从字符串转换为十进制

.net - .NET JSON解析器比较

c# - 通过自定义 IContractResolver 修改/添加属性

c# - Linq 在没有具体类型的情况下动态构建查询

c# - 从 .net 调用存储过程

c# - 全尺寸 Silverlight 应用程序尺寸

c# - Asp.net Mvc 5 中的 HttpPut?