由于某种原因,我偷偷进入类Double的.NET Framework源代码,发现==的声明是:

public static bool operator ==(Double left, Double right) {
    return left == right;
}

同样的逻辑适用于every运算符.


  • 这样的定义有什么意义?
  • 它是如何工作的?
  • 为什么它不创建一个无限递归呢?

推荐答案

实际上,编译器会将==运算符转换为ceq IL代码,并且不会调用您提到的运算符.

源代码中使用运算符的原因很可能是因为它可以从C#以外的语言调用,而C#不会直接(或通过反射)将其转换为CEQ调用.运算符will的代码within可以编译为CEQ,因此不存在无限递归.

事实上,如果您通过反射调用操作符,您可以看到操作符被调用(而不是CEQ指令),并且显然不是无限递归的(因为程序如预期的那样终止):

double d1 = 1.1;
double d2 = 2.2;

MethodInfo mi = typeof(Double).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public );

bool b = (bool)(mi.Invoke(null, new object[] {d1,d2}));

结果IL(由LinqPad 4编译):

IL_0000:  nop         
IL_0001:  ldc.r8      9A 99 99 99 99 99 F1 3F 
IL_000A:  stloc.0     // d1
IL_000B:  ldc.r8      9A 99 99 99 99 99 01 40 
IL_0014:  stloc.1     // d2
IL_0015:  ldtoken     System.Double
IL_001A:  call        System.Type.GetTypeFromHandle
IL_001F:  ldstr       "op_Equality"
IL_0024:  ldc.i4.s    18 
IL_0026:  call        System.Type.GetMethod
IL_002B:  stloc.2     // mi
IL_002C:  ldloc.2     // mi
IL_002D:  ldnull      
IL_002E:  ldc.i4.2    
IL_002F:  newarr      System.Object
IL_0034:  stloc.s     04 // CS$0$0000
IL_0036:  ldloc.s     04 // CS$0$0000
IL_0038:  ldc.i4.0    
IL_0039:  ldloc.0     // d1
IL_003A:  box         System.Double
IL_003F:  stelem.ref  
IL_0040:  ldloc.s     04 // CS$0$0000
IL_0042:  ldc.i4.1    
IL_0043:  ldloc.1     // d2
IL_0044:  box         System.Double
IL_0049:  stelem.ref  
IL_004A:  ldloc.s     04 // CS$0$0000
IL_004C:  callvirt    System.Reflection.MethodBase.Invoke
IL_0051:  unbox.any   System.Boolean
IL_0056:  stloc.3     // b
IL_0057:  ret 

有趣的是,积分类型不存在相同的运算符(无论是在参考源中还是通过反射),只有SingleDoubleDecimalStringDateTime,这推翻了我的理论,即它们的存在是为了从其他语言调用.显然,在其他语言中,如果没有这些运算符,你可以将两个整数等同起来,所以我们回到问题"double为什么存在它们"?

.net相关问答推荐

Docker失败文件找不到

为什么.Net 8.0.100是预览版?

Azure管道-使用.NET 8 RC2 SDK生成C#项目失败

保存时不保留 XML 格式

是否可以将 SandCastle 创建的两个页面合并到一个主页中?

托管和非托管代码、内存和大小有什么区别?

你如何调试 MVC 4 API 路由?

如何在不丢失数据的情况下重命名 Entity Framework 5 Code First 迁移中的数据库列?

操作对事务的状态无效错误和事务范围

公钥令牌的作用是什么?

形成两个列表并集的最简单方法

.Net 中 AOP 的最佳实现是什么?

如何从其十六进制 RGB 字符串创建 System.Drawing.Color?

Microsoft.Bcl.Build NuGet 包有什么作用?

如何将 Excel 序列日期编号转换为 .NET DateTime?

说明 C# 中 volatile 关键字的用法

功能说明

如何在 C# 中处理 XML

如何重新启动我的 C# WinForm 应用程序?

连接字符串而不是使用一堆 TextBlocks