【转载】C#中的==、Equal、ReferenceEqual

【转载】C#中的==、Equal、ReferenceEqual

1. ReferenceEquals, == , Equals
Equals , == , ReferenceEquals都可以用于判断两个对象的个体是不是相等。

a) ReferenceEquals
ReferenceEquals是Object的静态方法,用于比较两个引用类型的对象是否是对于同一个对象的引用。对于值类型它总是返回false。(因为Box以后的对象总是不同的,hehe)

b) ==是一个可以重载的二元操作符,可以用于比较两个对象是否相等。
对于内置值类型,==判断的是两个对象的代数值是否相等。它会根据需要自动进行必要的类型转换,并根据两个对象的值是否相等返回true或者false。例如:

Int a = 100;
Double b =100;

If(a == b)
Console.WriteLine(“equal supports compare between different types!”);

上面这段程序将会输出:
equal supports compare between different types!

而对于用户定义的值类型,如果没有重载==操作符,==将是不能够使用的。例如:
Struct Userstruct1;
Userstruct1 a;
Userstruct1 b;

If(a == b)
Console.WriteLine(“can == reach this far?”)

上面的这段代码是不能够通过编译的。可以通过重载使==作用于用户定义的值类型。

对于引用类型,== 默认的行为与ReferenceEquals的行为相同,仅有两个对象指向同一个Reference的时候才返回true。但是.NET Framework中的类很多对==进行了重载,例如String类的==与Equals的行为相同,判断两个字符串的内容是否相等。所以在应用中,对于 系统定义的引用类型建议不要使用==操作符,以免程序出现与预期不同的运行结果。

c) Equals 作为Object内置方法,Equals支持对于任意两个CTS对象的比较。
Equals它有静态方法和可重载的一个版本,下面的程序片断解释了这两个方法的用法,

int a = 5;
int b = 5;

If(Object.Equals(a ,b))
// you can also use if(a.Equals(b))
{
Console.WriteLine(“a is equal to b”);
}

事实上,这两个版本的结果完全相同,如果用户重载了Equals,调用的都是用户重载后的Equals。Equals的静态方法的好处是可以不必考虑用于比较的对象是否为null。

Equals方法对于值类型和引用类型的定义不同,对于值类型,类型相同,并且数值相同(对于struct的每个成员都必须相同),则Equals返回 true,否则返回false。而对于引用类型,默认的行为与ReferenceEquals的行为相同,仅有两个对象指向同一个Reference的时 候才返回true。可以根据需要对Equals进行重载,例如String类的Equals用于判断两个字符串的内容是否相等。

StringBuilder a = new StringBuilder();
a.Append(“the test a”);
String s1 = a.ToString();
String s2 = “the test a”;

if (s2 == s1)
Console.WriteLine(“== returns true”);

if (Object.Equals(s2, s1))
{
Console.WriteLine(“equals returns true”);
}

if (Object.ReferenceEquals(s2, s1))
{
Console.WriteLine(“ReferenceEquals returns true”);
}

这个实例将输出:
== returns true
equals returns true

注:对于String类,直接声明s1 = “the test a”的话,输出结果将包含 “ReferenceEquals returns true”,
因为默认的,String对于声明的相同的字符串在堆上只保留一个Copy,所以s1与s2将会指向相同的Reference

在C#中,有多种比较方法,有referenceequal,equals,equalsto,但他们之间是有细微差别的。

referenceequal的实例

class MyClass {

   static void Main() {
      object o = null;
      object p = null;
      object q = new Object();

      Console.WriteLine(Object.ReferenceEquals(o, p));
      p = q;
      Console.WriteLine(Object.ReferenceEquals(p, q));
      Console.WriteLine(Object.ReferenceEquals(o, p));
   }
如果要是对象都指向空引用,那么它返回true,另外,p=q;这个赋值语句,对于值类型来说,只是把地址复制给了p,并没有深拷贝。所以当比较引用时,返回true。如果比较o.equals(p),那么编译器会报错,因为equals方法不能比较null的情况。正因为如此,referenceequals方法才不受开发人员欢迎。另外,equals为实例的虚方法,referenceequals为静态方法。基元类型的==,就是操作符重载,使用的 equals方法判等。当然,还有一个equals的静态方法,静态equals与实例equals方法的唯一区别是:实例equals在对2个进行比较时,如果有一个为null,或者都是null,就会抛出异常,但静态equals方法不会,静态equals方法首先对2者检查是否为null,如果有为null的情况,就返回false,如果没有null,那么就调用实例equals方法来进行比较。

memberwiseclone()翻译为成员智能复制,呵呵,为啥智能,我就讲讲。智能就在它区别对待值类型和引用类型。

MemberwiseClone 方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。如果字段是值类型的,则对该字段执行逐位复制。如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。

例如,考虑一个名为 X 的对象,该对象引用对象 A 和 B。对象 B 又引用对象 C。X 的浅表副本创建一个新对象 X2,该对象也引用对象 A 和 B。与此相对照,X 的深层副本创建一个新对象 X2,该对象引用新对象 A2 和 B2,它们分别是 A 和 B 的副本。B2 又引用新对象 C2,C2 是 C 的副本。

关于深拷贝和浅拷贝,深拷贝就是创建一个一摸一样的对象,浅拷贝的话仍然是同一个对象,但是却有2个计数器,2个强引用指向它。

 

【转自】http://www.cnblogs.com/zagelover/articles/2741409.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119339.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 因果图与判定表法_因果图如何转换为判断表

    因果图与判定表法_因果图如何转换为判断表1、什么是因果图及判定表法?因果图是用图解的方法表示输入的各种组合关系,依据因果图写出判定表,从而设计相应的测试用例。它适合于检查程序输入条件的各种组合情况。例约束关系、组合关系。2、因果图之4种因果关系(注:0表示某状态不出现,1表示某状态出现)恒等:若c1是1,则e1也为1;否则e1为0非:若c1是1,则e1也为0;否则e1为1或:若…

    2022年8月14日
    6
  • 如何干净卸载_怎么把360卸载干净

    如何干净卸载_怎么把360卸载干净Oracle大家都知道下载简单,但是想卸载,没那么轻松,会发现自己卸载不干净,导致再次安装就会失败,现在我就一步一步演示如何彻底卸载Oracle,然后再重新安装。(本机win10)1.停止系统中所有的Oracle服务(win+r—-taskmgr—–服务)2.运行UniversalInstallera、点击应用b、卸载产品c、选择Orac…

    2022年10月21日
    3
  • 几何角度理解叉乘

    几何角度理解叉乘简介 本文解释了叉乘的计算 行列式 和几何解释之间的关系 1 叉乘的计算及几何解释在我学习叉乘 本文只考虑三维向量 的时候 老师教了我们两个东西 叉乘的计算方法 用行列式 设有向量 v v1 v2 v3 w w1 w2 w3 vec v v 1 v 2 v 3 quad vec w w 1 w 2 w 3 quadv v1 v2 v3

    2025年6月25日
    3
  • docker项目经验_如何培育与指导部署

    docker项目经验_如何培育与指导部署每个人的前半生,都在不停地做加法。可到了后半生,我们就要学会不断地做减法。目录前置工作1、需要准备的东西2、连接云服务器安装Docker环境1、安装Docker的依赖库。2、添加DockerCE的软件源信息。3、安装DockerCE。4、启动Docker服务。准备Dockerfile并部署项目(构建新的业务镜像)1、准备nginx.conf.template、Dockerfile、dist(前端项目build后的包)2、部署项目知识点(需要…

    2022年10月19日
    4
  • VMWARE虚拟机上网三种方法分析

    VMWARE虚拟机上网三种方法分析VMWARE虚拟机不能上网三种方法分析  PostBy:2009-1-2320:43:00 bridged(桥接模式)、NAT(网络地址转换模式)host-only(主机模式)。理论理解:1.bridged(桥接模式)在这处模式下,虚拟机等同于网络内的一台物理主机,可对手动设置IP,子网掩码,DNS,且IP地址要和主机的IP在同一网段内。这样,虚拟机就和主

    2022年5月19日
    37
  • vue如何引用js文件_html转化为vue组件

    vue如何引用js文件_html转化为vue组件VUE项目中引入JS文件的几种方法在开发Vue项目的时候,有时需要使用一些非ES6格式的没有export的js库,可以有如下方法实现:1.在index.html页面使用script标签引入当然也可以使用cdn的地址。这样引入后的内容是全局的,可以在所有地方使用。Map2.在main.js中使用window.moduleName使用也可以放入Vue.prototype中,这样组件内都可以使用。va…

    2022年10月8日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号