C#值类型、引用类型中的Equals和==的区别浅析

C#值类型、引用类型中的Equals和==的区别浅析

相关概念

在讨论 Equals== 的区别之前,我们先来了解一下 C# 中两种常见的数据类型:值类型和引用类型。

值类型

值类型指的是简单的数据类型,如 intdoublechar 等等。值类型的数据在赋值和传递时,始终是复制一份数据,而不是像引用类型那样复制一份指向数据的指针。

int a = 1;
int b = a;

以上代码中,第二行的赋值操作不会影响第一行的变量 a,因为 int 是一个值类型,所以 b 将完全复制 a 中的值。

引用类型

引用类型则是指向某个对象的引用,而不是该对象本身。常见的引用类型包括 string 和自定义的类、接口等等。引用类型的数据在赋值和传递时,实际上是复制了一份指向同一个对象的引用,而不是复制了一个新的对象。

string s1 = "hello";
string s2 = s1;

以上代码中,第二行的赋值操作将使 s2 引用与 s1 引用指向同一个 string 对象。如果修改了 s2 的值,则实际上也会修改 s1 对应的字符串。

Equals 和 == 的区别

值类型中的 Equals 和 ==

在值类型中,Equals== 的作用是类似的,都是用来比较值是否相等的。区别在于:

  • Equals 可以被重写,而 == 操作符不行
  • Equals 需要一个对象作为参数,而 == 操作符可以直接比较两个值类型的值
int a = 1;
int b = 2;
bool equal1 = a.Equals(b);  // false
bool equal2 = (a == b);     // false

// 重写 Equals 方法
struct MyStruct
{
    public int X;
    public int Y;

    public override bool Equals(object obj)
    {
        if (obj is MyStruct)
        {
            MyStruct other = (MyStruct)obj;
            return (this.X == other.X && this.Y == other.Y);
        }
        return false;
    }
}

MyStruct s1 = new MyStruct { X = 1, Y = 2 };
MyStruct s2 = new MyStruct { X = 1, Y = 2 };
bool equal3 = s1.Equals(s2);  // true
bool equal4 = (s1 == s2);     // false,因为 MyStruct 没有重载 == 操作符

引用类型中的 Equals 和 ==

在引用类型中,Equals== 的作用不一样了:

  • Equals 用于判断两个对象的值是否相等
  • == 用于判断两个对象的引用是否相等

换句话说,如果想比较引用类型的值是否相等,应该使用 Equals 方法;如果想比较两个引用类型的对象是否是同一个对象,应该使用 == 操作符。

string s1 = "hello";
string s2 = "HELLO".ToLower();
bool equal1 = s1.Equals(s2);  // true,因为两个字符串的值相等
bool equal2 = (s1 == s2);     // false,因为 s1 和 s2 引用的不是同一个字符串对象

示例

示例一:对象引用为 null

string s1 = null;
string s2 = null;
bool equal1 = s1.Equals(s2);  // 抛出 NullReferenceException 异常
bool equal2 = (s1 == s2);     // true

以上代码中,由于 s1s2 引用都为 null,因此使用 s1.Equals(s2) 方法时会抛出 NullReferenceException 异常。但是,s1 == s2 会返回 true,因为两个引用都是 null

示例二:自定义类重载 Equals 方法

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public override bool Equals(object obj)
    {
        if (obj is Person)
        {
            Person other = (Person)obj;
            return (this.Name == other.Name && this.Age == other.Age);
        }
        return false;
    }
}

Person p1 = new Person { Name = "Alice", Age = 25 };
Person p2 = new Person { Name = "Alice", Age = 25 };
bool equal1 = p1.Equals(p2);  // true
bool equal2 = (p1 == p2);     // false

以上代码中,自定义了一个 Person 类,并重载了它的 Equals 方法,用于比较两个 Person 对象的值是否相等。在比较 p1p2 时,通过 p1.Equals(p2) 方法可以正确地判断两个对象的值是否相等。但是,p1 == p2 操作符却会返回 false,因为 Person 类没有重载 == 操作符。如果需要使 == 操作符可以比较两个 Person 对象的值是否相等,还需要在 Person 类中定义相应的 == 操作符重载方法。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#值类型、引用类型中的Equals和==的区别浅析 - Python技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • C#中split用法实例总结

    C#中split用法实例总结 在C#编程中,经常需要处理字符串。字符串常常需要拆分成不同的部分进行处理,这时就需要使用split方法。本文将详细讲解C#中split用法及实例应用。 split方法的基本用法 split方法是C#中常用的字符串拆分方法,其基本原型为: public string[] Split(params char[] separator)…

    C# 2023年6月7日
    00
  • C#实现复杂XML的序列化与反序列化

    下面是“C#实现复杂XML的序列化与反序列化”的完整攻略。 简介 XML是一种通用的数据交换格式,它被广泛地应用在各种场景中。当我们需要将.NET对象序列化为XML格式时,C#提供了许多序列化工具,其中XmlSerializer是最常用的。本攻略主要介绍如何使用XmlSerializer来实现复杂XML的序列化与反序列化。 序列化 序列化是将.NET对象转换…

    C# 2023年5月31日
    00
  • ASP.NET Core设置Ocelot网关限流

    ASP.NET Core设置Ocelot网关限流 Ocelot是一个基于.NET Core的API网关,它可以帮助我们将多个微服务组合成一个整体的API。在实际应用中,我们可能需要对API网关进行限流,以保证系统的稳定性和可靠性。本攻略将详细介绍如何在ASP.NET Core中使用Ocelot实现API网关限流。 安装Ocelot 首先,我们需要安装Ocel…

    C# 2023年5月17日
    00
  • .NetCore利用BlockingCollection实现简易消息队列

    .NET Core利用BlockingCollection实现简易消息队列 在.NET Core应用程序中,我们可以使用BlockingCollection类来实现简易消息队列。本攻略将详细介绍如何使用BlockingCollection类来实现简易消息队列,并提供两个示例说明。 BlockingCollection类 BlockingCollection类…

    C# 2023年5月17日
    00
  • c# Graphics使用方法(画圆写字代码)

    C# Graphics使用方法(画圆写字代码) 在C#中,我们可以使用System.Drawing命名空间下的Graphics类来实现绘图功能,包括画笔、画刷、线条、形状等等。本篇攻略主要介绍如何使用Graphics类绘制圆和写字的相关代码。 创建 Graphics 对象 要使用Graphics类进行绘图,首先要创建Graphics对象。我们可以通过两种方式…

    C# 2023年6月7日
    00
  • C#中Serializable序列化实例详解

    下面是关于“C#中Serializable序列化实例详解”的完整攻略,包含两个示例。 1. Serializable序列化简介 Serializable是C#中的一个特性,用于将对象序列化为二进制格式,以便在网络上传输或保存到文件中。在C#中,我们可以使用Serializable特性来标记一个类,以便将其序列化为二进制格式。以下是C#中Serializabl…

    C# 2023年5月15日
    00
  • C#关键字Check简单介绍

    下面是针对“C#关键字Check简单介绍”的完整攻略。 C#关键字Check简单介绍 Check关键字的作用 在C#中,Check是一种辅助性关键字,主要用来进行代码调试和控制程序执行流程。 当使用Check关键字时,系统会对代码中的各个位置进行检查,从而帮助程序员发现潜在的问题,并输出相应的调试信息。 Check的语法 在C#中,Check关键字常常被用来…

    C# 2023年5月14日
    00
  • .net core中Grpc使用报错:The remote certificate is invalid according to the validation procedure.

    因为Grpc采用HTTP/2作为通信协议,默认采用LTS/SSL加密方式传输,比如使用.net core启动一个服务端(被调用方)时:   public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWe…

    C# 2023年4月17日
    00
合作推广
合作推广
分享本页
返回顶部