C# 相等性检测方法差异分析(==,Equals,ReferenceEquals)

news2024/9/28 5:47:07

先给结论:

对于每种类型创建2个一样的数据,比较结果如下表所示:

数据类型==EqualsReferenceEquals
int(值类型)×
引用类型×××
引用类型(带override)以operator ==实现为准以Equals覆写为准×
struct必须实现==操作符×
struct(带override)以operator ==实现为准以Equals覆写为准×
string×

一.比较操作符==

对于==的相等性检测,思路如下:

  1. 如果是struct,且没实现==操作符,则编译报错:
    在这里插入图片描述
  2. 如果实现了 == 操作符,则以 == 操作为准
  3. 如果是系统基础值类型,则可以直接判断值是否相等
  4. 如果是引用类型,则比较它们的引用是否相等,也就是栈上的保存的地址
public void Case1()
{
    TestClass testClass1 = new TestClass();
    TestClass testClass2 = new TestClass();

    Console.WriteLine($"testClass2 == testClass1 :{testClass2 == testClass1}");	 //输出: false
}
  1. 如果是string,因为string实现了==操作符,实际比较的是stirng内保存的内容是否相等
    这里可以看到C#对于 == 与Equals的实现,其实比较的实际存储的数据
public static bool operator == (String a, String b) {
	return String.Equals(a, b);
}

public static bool Equals(String a, String b) {
    if ((Object)a==(Object)b) {
        return true;
    }

    if ((Object)a==null || (Object)b==null) {
        return false;
    }

    if (a.Length != b.Length)
        return false;

    return EqualsHelper(a, b);
}

private unsafe static bool EqualsHelper(String strA, String strB)
{
    Contract.Requires(strA != null);
    Contract.Requires(strB != null);
    Contract.Requires(strA.Length == strB.Length);

    int length = strA.Length;

    fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
    {
        char* a = ap;
        char* b = bp;

        // unroll the loop
#if AMD64
        // for AMD64 bit platform we unroll by 12 and
        // check 3 qword at a time. This is less code
        // than the 32 bit case and is shorter
        // pathlength

        while (length >= 12)
        {
            if (*(long*)a     != *(long*)b) return false;
            if (*(long*)(a+4) != *(long*)(b+4)) return false;
            if (*(long*)(a+8) != *(long*)(b+8)) return false;
            a += 12; b += 12; length -= 12;
        }
#else
        while (length >= 10)
        {
            if (*(int*)a != *(int*)b) return false;
            if (*(int*)(a+2) != *(int*)(b+2)) return false;
            if (*(int*)(a+4) != *(int*)(b+4)) return false;
            if (*(int*)(a+6) != *(int*)(b+6)) return false;
            if (*(int*)(a+8) != *(int*)(b+8)) return false;
            a += 10; b += 10; length -= 10;
        }
#endif

        // This depends on the fact that the String objects are
        // always zero terminated and that the terminating zero is not included
        // in the length. For odd string sizes, the last compare will include
        // the zero terminator.
        while (length > 0) 
        {
            if (*(int*)a != *(int*)b) break;
            a += 2; b += 2; length -= 2;
        }

        return (length <= 0);
    }
}

二. Equals方法

在C#中,Equals是一个虚拟方法,它用于比较对象的内容是否相等。Equals方法是从System.Object基类继承而来,因此所有的C#类型都继承了Equals方法,但是默认情况下,对于引用类型而言,Equals方法只比较它们的引用是否相等,而不比较对象的内容。

  1. 覆写了Equals方法:以方法实现为准
  2. 基础值类型,struct:默认比较栈上存储的值是否相等
public void Case2()
 {
     TestStruct testStruct1 = new TestStruct()
     {
         _int = 10,
         _bool = false,
     };
     TestStruct testStruct2 = new TestStruct()
     {
         _int = 10,
         _bool = false,
     };
     Console.WriteLine($"testStruct1.Equals(testStruct2) :{testStruct1.Equals(testStruct2)}");	//输出: true
 }
  1. 引用类型:如果对象引用一致(栈内容),则相等
public void Case1()
{
    TestClass testClass1 = new TestClass();
    TestClass testClass2 = new TestClass();

    Console.WriteLine($"testClass2.Equals(testClass1) :{testClass2.Equals(testClass1)}");
}
  1. string类型:跟==实现一样,都覆写了Equals方法,比较的是实际内容

三.ReferenceEquals方法

在C#中,ReferenceEquals是一个静态方法,用于确定两个引用变量是否引用同一个对象(即两个引用是否指向同一内存地址)。ReferenceEquals方法是在System.Object类中定义的

  1. 对于值类型,默认会将值类型先装箱,转换成Object类型,这相当于创建了2个新对象,肯定不相等
 public void Case3()
 {
     int int1 = 10;
     int int2 = 10;
     Console.WriteLine($"ReferenceEquals(int1, int2) :{ReferenceEquals(int1, int2)}");  //输出: false
 }

在这里插入图片描述

  1. 对于string引用类型,则,直接比较的是引用(栈上保存)是否一致
public void Case5()
{
    string str1 = "Hello";
    string str2 = "Hello";
    Console.WriteLine(ReferenceEquals(str1, str2));  // 输出: false
    
    string str3 = str1;
    Console.WriteLine(ReferenceEquals(str1, str3));  // 输出: true
}

使用方法

  1. 对于系统内置值类型:直接使用==即可,也可以使用Equals,但是不能使用ReferenceEquals(装箱GC,且不能判断相等)
  2. 对于结构体:建议自定义实现操作符==,且覆写Equals方法
  3. 对于引用类型:如果只需要判断引用相当,都可以使用,但是如果要判断数据内保存的内容相等,则需要自己实现操作符==,且覆写Equals方法
  4. 对于string:默认全部都是比较的内容相等性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2172542.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【BurpSuite】访问控制漏洞和权限提升 | Access control vulnerabilities (3-6)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【BurpSuite】访问控制漏洞和权限提升 | Access control vulnerabilities (3-6&#xff09; 实验三 Lab: User role controlled b…

【高频SQL基础50题】6-10

目录 1.上级经理已离职的公司员工 2.修复表中的名字 3. 寻找用户推荐人 4.产品销售分析 I 5.平均售价 1.上级经理已离职的公司员工 子查询。 先根据薪水大小查询&#xff0c;再根据manager_id查询该员工是否存在&#xff0c;最后做排序。 # Write your MySQL query st…

ValueError: Out of range float values are not JSON compliant

可能原因一 可能原因二 数据里面有NaN

C++八股进阶

之前那个只是总结了一下常考点&#xff0c;这个是纯手打记笔记加深理解 这里写目录标题 C的四种智能指针为什么要使用智能指针&#xff1f;四种智能指针&#xff1a; C中的内存分配情况C中的指针参数传递和引用参数传递C 中 const 和 static 关键字&#xff08;定义&#xff0…

Linux云计算 |【第四阶段】PROJECT2-DAY2

综合项目内容&#xff1a; 升级网站运行平台、部署Redis内存存储服务集群、数据迁移、部署PXCMySQL实现强同步、部署LB和HA集群 一、项目拓扑结构 PROJECT2-DAY1回顾&#xff1a; 服务架构缺点分析&#xff1a; ① 数据存储结构存在单点故障&#xff08;需增调度器&#xff0…

STM32低功耗实验学习日记

STM32低功耗实验学习日记 写于2024/9/25晚 文章目录 STM32低功耗实验学习日记1. 简介2. STM32F1电源系统2.1 电源系统2.2 电源管理2.2.1 睡眠模式2.2.2 停止模式2.2.3 待机模式 2.3 相关寄存器介绍2.3.1 系统控制寄存器(SCB_SCR)2.3.2 电源控制寄存器(PWR_CR)2.3.3 电源控制/状…

智能BI项目第六期

本期任务 分析系统现在的不足分布式消息队列分布式消息队列 RabbitMQ 入门实战 系统现状不足分析总结 让我们来讨论一下单机系统的问题。 现状&#xff1a;我们的异步处理是通过本地线程池实现的。 但是存在以下问题&#xff1a; 无法集中限制&#xff0c;仅能单机限制&a…

kafka监控平台Kafdrop:使用记录

背景 AI的发展真是太方便了&#xff0c;让它给我推荐一款轻量级&#xff0c;没有学习曲线的kafka监控平台&#xff0c;它就给我推荐这一款。用了一下果然没有一点学习曲线。 目前已经满足了我的需求&#xff0c;可视化界面&#xff0c;topic、消息、消费者group信息以及消费情…

【项目经验分享】深度学习点云算法毕业设计项目案例定制

以下是深度学习与点云算法相关的毕业设计项目案例&#xff0c;涵盖了点云数据的分类、分割、重建、配准、目标检测等多个领域&#xff0c;适用于智能驾驶、机器人导航、3D建模等多个应用场景&#xff1a; 案例截图&#xff1a; 基于PointNet的3D点云分类与分割PointNet在大规…

2-105 基于matlab的GA-WNN预测算法

基于matlab的GA-WNN预测算法。遗传算法优化小波神经网络的步骤&#xff1a;1设种群规模为M。随机生成初始种群N , 采用实数编码对个体Ni编码。2、用1中的种群N训练, WNN参数由初始化获得。3、计算种群N中个体适应度值。满足终止条件则跳至6, 不满足执行4。4、适应度大的个体, 选…

基于Hive和Hadoop的白酒分析系统

本项目是一个基于大数据技术的白酒分析系统&#xff0c;旨在为用户提供全面的白酒市场信息和深入的价格分析。系统采用 Hadoop 平台进行大规模数据存储和处理&#xff0c;利用 MapReduce 进行数据分析和处理&#xff0c;通过 Sqoop 实现数据的导入导出&#xff0c;以 Spark 为核…

每日论文5—06TCAS2锁相环电流匹配的gain-boosting电荷泵

《Gain-Boosting Charge Pump for Current Matching in Phase-Locked Loop》 06TCAS2 本质上和cascode来增加输出电阻&#xff0c;从而减小电流变化的思路是一样的。这里用了放大器来增加输出电阻。具体做法如下图&#xff1a; 如图1(a)&#xff0c;A3把Vb和Vx拉平&#xff0…

GPT理论

1.GPT发展 Transformer是一个用作翻译任务的模型&#xff0c;谷歌出品。 GPT全称 lmproving Language Understanding by Generative Pre-Training&#xff0c;用预训练语言理解模型。OPENAI出品。 BERT全称Pre-training of Deep BidirectionalTransformers for Language Unde…

从 Kafka 到 WarpStream: 用 MinIO 简化数据流

虽然 Apache Kafka 长期以来一直是流数据的行业标准&#xff0c;但新的创新替代方案正在重塑生态系统。其中之一是 WarpStream&#xff0c;它最近在 Confluent 的所有权下进入了新的篇章。此次收购进一步增强了 WarpStream 提供高性能、云原生数据流的能力&#xff0c;巩固了其…

数据结构与算法——Java实现 19.队列

目录 一、概述 二、链表实现队列 接口定义 接口实现类 测试类 三、环形数组实现队列 优点 下标计算 判满和判空 判满 判空 辅助变量size判空和判满 方法1 接口定义 接口实现类 测试类 方式2 接口定义 接口实现类 测试类 方法3 接口定义 接口实现类 测试类 生活鲜少给人留下退…

C语言 | Leetcode C语言题解之第440题字典序的第K小数字

题目&#xff1a; 题解&#xff1a; #define MIN(x, y) ((x) < (y) ? (x) : (y))int getSteps(int curr, long n) {int steps 0;long first curr;long last curr;while (first < n) {steps MIN(last, n) - first 1;first first * 10;last last * 10 9;}return …

WMware安装WMware Tools(Linux~Ubuntu)

1、这里终端里面输入sudo apt upgrade用于更新最新的包 sudo apt upgrade 2、安装 open-vm-tools-desktop 包&#xff0c; Ps&#xff1a;这里是以为我已经安装好了。 udo apt install open-vm-tools-desktop -y3、最后重启就大功告成了 reboot 4、测试是否成功&#xff1a…

翻译器在线翻译:开启多语言交流新时代

随着国际交流、商务合作、文化交融以及互联网的飞速发展&#xff0c;人们对于跨越语言鸿沟的需求日益迫切。翻译工具成为了我们必备的一个工具&#xff0c;这篇文章我们一起来探讨一些好用的翻译器在线翻译工具吧。 1.在线福昕翻译 链接直达>>https://fanyi.pdf365.cn/…

[贪心+数学/数学+位运算] 两种方法O(1)解决 消减整数

标题&#xff1a;[贪心数学/数学位运算] 两种方法O(1)解决 消减整数 个人主页水墨不写bug 目录 一、题目&#xff1a;消减整数(Newcoder) 二、题目分析 1.理解题意&#xff1a; 2.解决问题 解法详解一&#xff1a;贪心数学 解法一参考代码&#xff1a; 解法详解二&#xf…

【RabbitMQ——具体使用场景】

1. 异步 1.1 同步异步的问题&#xff08;串行&#xff09; 串行方式&#xff1a;将订单信息写入数据库成功后&#xff0c;发送注册邮件&#xff0c;再发送注册短信。以上三个任务全部完成后&#xff0c;返回给客户端 public void makeOrder(){// 1 :保存订单 orderService.…