为什么长整型和小数之间的等于不可交换?

2024-04-22

我在 linqpad 中运行以下代码:

    long x = long.MaxValue;
    decimal y = x;

    x.Dump();
    y.Dump();

    (x == y).Dump();
    (y == x).Dump();

    Object.Equals(x, y).Dump();
    Object.Equals(y, x).Dump();
    x.Equals(y).Dump();
    y.Equals(x).Dump();

它产生以下输出:

    9223372036854775807
    9223372036854775807
    True
    True
    False
    False
    False
    True

请注意最后两行:x.Equals(y) 为 false,但 y.Equals(x) 为 true。因此,小数认为自己等于具有相同值的长整型,但长整型不认为自己等于具有相同值的小数。

这种行为的解释是什么?

Update:

我接受了李的回答。

我对此很好奇并编写了这个小程序:

using System;
namespace TestConversion
{
  class Program
  {
    static void Main(string[] args)
    {
      long x = long.MaxValue;
      decimal y = x;

      Console.WriteLine(x);
      Console.WriteLine(y);

      Console.WriteLine(x == y);
      Console.WriteLine(y == x);

      Console.WriteLine(Object.Equals(x, y));
      Console.WriteLine(Object.Equals(y, x));
      Console.WriteLine(x.Equals(y));
      Console.WriteLine(y.Equals(x));
      Console.ReadKey();
    }
  }
}

然后我在 IL 中对其进行了反汇编:

.method private hidebysig static void Main(string[] args) cil managed
{
  .entrypoint
  .maxstack 2
  .locals init (
    [0] int64 x,
    [1] valuetype [mscorlib]System.Decimal y)
  L_0000: nop 
  L_0001: ldc.i8 9223372036854775807
  L_000a: stloc.0 
  L_000b: ldloc.0 
  L_000c: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(int64)
  L_0011: stloc.1 
  L_0012: ldloc.0 
  L_0013: call void [mscorlib]System.Console::WriteLine(int64)
  L_0018: nop 
  L_0019: ldloc.1 
  L_001a: call void [mscorlib]System.Console::WriteLine(valuetype [mscorlib]System.Decimal)
  L_001f: nop 
  L_0020: ldloc.0 
  L_0021: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(int64)
  L_0026: ldloc.1 
  L_0027: call bool [mscorlib]System.Decimal::op_Equality(valuetype [mscorlib]System.Decimal, valuetype [mscorlib]System.Decimal)
  L_002c: call void [mscorlib]System.Console::WriteLine(bool)
  L_0031: nop 
  L_0032: ldloc.1 
  L_0033: ldloc.0 
  L_0034: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(int64)
  L_0039: call bool [mscorlib]System.Decimal::op_Equality(valuetype [mscorlib]System.Decimal, valuetype [mscorlib]System.Decimal)
  L_003e: call void [mscorlib]System.Console::WriteLine(bool)
  L_0043: nop 
  L_0044: ldloc.0 
  L_0045: box int64
  L_004a: ldloc.1 
  L_004b: box [mscorlib]System.Decimal
  L_0050: call bool [mscorlib]System.Object::Equals(object, object)
  L_0055: call void [mscorlib]System.Console::WriteLine(bool)
  L_005a: nop 
  L_005b: ldloc.1 
  L_005c: box [mscorlib]System.Decimal
  L_0061: ldloc.0 
  L_0062: box int64
  L_0067: call bool [mscorlib]System.Object::Equals(object, object)
  L_006c: call void [mscorlib]System.Console::WriteLine(bool)
  L_0071: nop 
  L_0072: ldloca.s x
  L_0074: ldloc.1 
  L_0075: box [mscorlib]System.Decimal
  L_007a: call instance bool [mscorlib]System.Int64::Equals(object)
  L_007f: call void [mscorlib]System.Console::WriteLine(bool)
  L_0084: nop 
  L_0085: ldloca.s y
  L_0087: ldloc.0 
  L_0088: call valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Implicit(int64)
  L_008d: call instance bool [mscorlib]System.Decimal::Equals(valuetype [mscorlib]System.Decimal)
  L_0092: call void [mscorlib]System.Console::WriteLine(bool)
  L_0097: nop 
  L_0098: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  L_009d: pop 
  L_009e: ret 
}

您确实可以看到长整型值已转换为十进制。

感谢你们!


发生这种情况是因为在

y.Equals(x);

the decimal.Equals(decimal)正在调用重载,因为有一个隐式转换 https://msdn.microsoft.com/en-us/library/ms131061.aspx之间long and decimal。结果比较返回 true。

但是,由于没有从decimal to long

x.Equals(y)

calls long.Equals(object)什么导致y被装箱并比较返回false因为它不能长时间拆箱。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么长整型和小数之间的等于不可交换? 的相关文章

随机推荐

  • 货币数据类型精度 - SQL Server (SSMS)

    在sql server management studio中 数据类型 金钱 当我输入带有小数的金额时 它会自动添加零以填充到百分之一 如何确定小数点后的空格数 点后面零的个数称为precision的一种数据类型 这money数据类型有一个
  • Swagger Editor 3.8 示例不适用于参考数组模式

    这个问题是后续问题这个类似的 https stackoverflow com q 52595690 1571426 正如 Helen 要求提出一个新问题 数组类型模式似乎只接受 示例 而不接受 示例 以下架构会产生错误编辑器 swagger
  • Android 8 本机库崩溃

    自从 Android 8 Oreo 推出以来 我们的应用程序一直在不同的地方崩溃 所有 Play 商店崩溃报告都显示本机崩溃 最常出现的一个似乎是在本机库中 最常崩溃的设备是 Google Pixel Pixel XL 也出现过一些崩溃 我
  • Javascript 随机定位 Div 且不重叠它们

    我一直在研究一个随机的概念想法 即让 6 个云出现在一个页面上 并从数据库中提取随机评论 这部分很简单 但我发现确保 6 朵云不相互重叠非常困难 我对碰撞检测进行了很多研究 发现在将新的 随机定位 div 放置在页面上之前 没有真正合适的方
  • 我的车库里真的有一辆车吗? [复制]

    这个问题在这里已经有答案了 我是 Java 编程的新手 正在尝试掌握 OOP 所以我构建了这个抽象类 public abstract class Vehicle 和2个子类 public class Car extends Vehicle
  • 无法解析“adb version”的输出

    我使用 Ubuntu 11 10 和 Eclipse 进行 Android 开发 我已经创建了一个新项目 但它包含错误 Failed to parse the output of adb version 如果有人知道我该如何解决这个问题 我
  • 如何在swift中插入子层?

    我正在创建一个视图并向其添加渐变层 我有这个 import UIKit import QuartzCore let rect CGRect CGRectMake 0 0 320 100 var vista UIView init frame
  • 如何在 Clojure 中更新原子的向量元素?

    我有一个矢量原子 我想更新一个本身就是地图的条目 def vector atom atom swap vector atom conj id 1 name myname 我该如何只更新该成员 在可变的 Java 领域的思维方式中 我会做这样
  • Windows窗体中如何设置滚动条

    我在 net中有一个winform 我放置了太多控件并设置了表单的高度和宽度 但是 当我编译表单并减小表单的大小时 我的控件不可见 当我增加表单的大小时 控件在自己的位置可见 我希望在减小表单大小时出现滚动条 并在增加表单大小时使滚动条消失
  • 将网页中的表格导入 Excel

    我只有中高级的Excel水平和中级的VBA与Excel背景 我想要做的是从链接中显示的网页导入表格 http www admission unmsm edu pe res20130914 A 011 0 html http www admi
  • 如何使用 Spring Batch 进行聚合?

    我想弄清楚如何使用 Spring Batch 进行聚合 例如 我有一个包含姓名列表的 CSV 文件 name John Amy John Ryan 我想要文本文件中的名称计数 name count Amy 1 John 2 Ryan 1 根
  • 如何在错误的 API url 上返回 404? (ASP.NET 核心 + SPA)

    我需要在错误的 api 调用上返回 404 以便我可以在客户端 Angular 5 上为用户创建正确的响应 目前后端返回状态码200和index html 这会导致前端出现json解析错误 我使用 ASP NET Core 2 1 和 An
  • 如何在 JavaScript 中解析文本中的单词?

    在文本页面中 我想检查每个单词 当时阅读每个单词的最佳方式是什么 找到被空格包围的单词很容易 但是一旦你开始解析文本中的单词 它就会变得复杂 是否有一些已经构建的东西可以解析正则表达式或其他方法中的单词 而不是定义我自己的从文本中解析单词的
  • 您应该将应用程序属性放在 rebar erlang 应用程序中的什么位置?

    新手问题 我编写了第一个基于 rebar 的 erlang 应用程序 我想配置一些基本属性 例如服务器主机等 放置它们的最佳位置在哪里以及如何将它们加载到应用程序中 接下来的步骤是发布版本并在其中创建节点 节点在独立的 Erlang VM
  • 有人有使用私有 Launchpad 实例的经验吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有人已经在自己的服务器上安装并运行启动板了吗 我想要建议 因为我在网上找不到任何建议 此外 官方团队还对拥有自己的启动板发表了可怕的言论 他们还
  • 将google云函数连接到oracle数据库

    有谁知道如何将谷歌云函数 Python 连接到Oracle数据库 我尝试在云函数中导入cx Oracle库 但它显示一个错误 函数加载错误 DPI 1047 无法加载 Oracle 客户端库 libclntsh so 无法打开共享对象文件
  • 使用多个管道从 Python 执行 Shell 脚本

    我想在 python 脚本中执行以下 Shell 命令 dom myserver cat etc xen myserver cfg grep limited cut d f2 tr d 我有这个 dom myserver limit sub
  • 如何设置 GMT 日期的时、分、秒

    我有日期对象 我想从我的日期中清除小时 分钟和秒 请帮助我如何在 Javascript 中执行此操作 我做错了吗 var date Date Fri 26 Sep 2014 18 30 00 GMT date setHours 0 date
  • 如何模拟 AngularJS 指令的控制器

    给定一个具有外部控制器的指令 directive d1 function return controller d1controller restrict E link function scope element attributes co
  • 为什么长整型和小数之间的等于不可交换?

    我在 linqpad 中运行以下代码 long x long MaxValue decimal y x x Dump y Dump x y Dump y x Dump Object Equals x y Dump Object Equals