由于某种原因,我偷偷进入类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相关问答推荐

使用CLR将数据从Excel导入SQL Server时出错

使用 Powershell TOM 在 SSAS 表格中创建分区

IIS 发布 ASP.NET Core 应用程序而不关闭 IIS 网站

为什么具有可为空值的 struct 的 HashSet 非常慢?

什么是提升运算符?

为什么 .net 对字符串使用 UTF16 编码,但默认使用 UTF-8 来保存文件?

Gacutil.exe 成功添加程序集,但在资源管理器中无法查看程序集.为什么?

如何在没有抽象基类的情况下强制覆盖后代中的方法?

根源是什么?

如何解决请确保文件可访问并且它是有效的程序集或 COM 组件?

在 Moq Callback() 调用中设置变量值

struct 中需要覆盖什么以确保平等正常运行?

运算符重载 ==, !=, Equals

String.Split 仅在 C# 中的第一个分隔符上?

静态析构函数

何时使用抽象类?

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

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

在 C# 中转义无效的 XML 字符

如何为我的 C# 应用程序创建产品密钥?