一、引言

今天在论坛中看到一位朋友提出这样的一个问题,问题大致(问题的链接为:http://social.msdn.microsoft.com/Forums/zh-CN/52e6c11f-ad28-4633-a434-fc4d09f4d23d )是这样的:

  static void Main(string[] args)
{
object m1 = ;
object m2 = ; Console.WriteLine(m1==m2); Console.WriteLine(m1.Equals(m2));
Console.Read();
}

大家先不要去Visual Studio中运行这段代码,先猜猜此段代码的运行结果是怎样的,如果你猜测的结果和运行出来的结果完全是一致并且你也知道原因的话,那这篇文章下面的内容就没必要看下去了,如果你对运行出来的结果表示不理解的话,那请继续看下面内容的分析,相信看完你绝对可以解除你的疑惑。

二、==与Equals的区别

上面问题的运行结果为:

对于结果为什么是这样的呢?这主要涉及到==与Equals方法的区别的,再讲两者的区别前,大家首先要明确——C#中有两种不同的相等:引用相等和值相等。值相等意味着两个对象保护相同的值,例如,两个值为1的整数就具有值相等性;引用相等意味着要比较的不是两个对象,而是两个对象的引用,且两者引用的是同一个对象。若要检查引用相等性,应使用 ReferenceEquals。若要检查值相等性,请使用 Equals(详细内容可以参考:http://msdn.microsoft.com/zh-cn/library/ms173147(v=vs.90).aspx )。下面就看看它们直接的区别:

  • ==比较的是栈内的内容,对于值类型而言,”==“比较的就是两个对象的值,除字符串(字符串类型是一个特殊情况)以外的引用类型比较的就是两个引用类型在栈内的地址
  • Equals方法是定义在Object中的虚方法,用来比较两者引用对象的值是否相等,.NET中类型就都可以重写Equals方法,例如,在.NET中string类型就重写了Equals方法,用于比较两个字符串的值是否相等,而不是字符串引用是否相等。

有了上面的理论基础,下面就具体分析上面程序为什么会是那样的结果:

  1. 首先m1,m2都是引用类型,当执行m1==m2操作时,比较的是m1与m2在栈内地址的值是否相等,即比较的是引用,因为m1和m2指向的是托管堆中1是不同的地址(这点大家可以通过在debug状态下内存窗口中查看),所以得到的结果就自然是false
  2. 对于m1.Equals(m2)比较的是m1与m2引用的值是否相等,因为它们都是引用托管堆中1,它们地址不等,但是值是相等的,都是1,所以返回为true。

下面用一道题目测试大家的掌握程度(也是为了进一步加深理解)

          static void Main(string[] args)
{
string str1 = "ZhangSan";
string str2 = "ZhangSan";
string str3 = new string(new char[] { 'z', 'h' });
string str4 = new string(new char[] { 'z', 'h'});
Console.WriteLine("str1 == str2 " + (str1 == str2).ToString());
Console.WriteLine("str1 Equals str2 " + str1.Equals(str2)); Console.WriteLine("str3 == str4 " + (str3 == str4).ToString());
Console.WriteLine("str3 Equals str4 " + str3.Equals(str4)); Console.Read();
}

运行结果为:

三、typeof与GetType区别

从上面那个问题中,我又联系到了typeof与GetType的区别,所以这里就一起总结下,首先我还是由一个程序来引出它们的区别:

           static void Main(string[] args)
{
object m1 = ;
object m2 = ;
// ValueType是引用类型,因为它是类,所以返回为false
Console.WriteLine(typeof(ValueType).IsValueType);
Console.WriteLine(m1.GetType().IsValueType);
Console.Read();
}

要想弄明白上面的运行结果,首先我们应该理解typeof与GetType的区别(之前我认为两个的都是一样的,这是一个误区),具体的区别为:

  • typeof 是运算符,而 GetType()是方法
  • typeof 获得类型的System.Type对象,GetType()获得当前实例的Type,
  • GetType()是基类System.Object的方法,只有建立了一个实例之后才能够被调用
  • typeof的参数只能是int, string, class,自定义类型,不能为具体实例,否则编译器会报错

知道它们的区别之后,结果也就很容易得到了,上面程序的运行结果为:

四、小结

这篇文章主要是记录下自己在回答问题时所学到的内容,也希望对有同样疑惑的朋友有所帮助。

[C# 基础知识系列]C#中易混淆的知识点的更多相关文章

  1. C#中易混淆的知识点

    C#中易混淆的知识点 一.引言 今天在论坛中看到一位朋友提出这样的一个问题,问题大致(问题的链接为:http://social.msdn.microsoft.com/Forums/zh-CN/52e6 ...

  2. 基础知识系列☞C#中→属性和字段的区别

    "好吧...准备写个'基础知识系列',算是记录下吧,时时看看,更加加深记忆···" 其实本来准备叫"面试系列"... 字段.属性.你先知道的哪个概念? ***我 ...

  3. 基础知识系列☞C#中数组Array、ArrayList和List三者的区别

    数组() #region 数组 //初始化方式_0:先声明再赋值 ]; weekDays_0[] = "Sun"; weekDays_0[] = "Mon"; ...

  4. [WPF 基础知识系列] —— 绑定中的数据校验Vaildation

    前言: 只要是有表单存在,那么就有可能有对数据的校验需求.如:判断是否为整数.判断电子邮件格式等等. WPF采用一种全新的方式 - Binding,来实现前台显示与后台数据进行交互,当然数据校验方式也 ...

  5. 基础知识系列☞C#中→委托

    有些.NET中的高级特性,比如:委托! 有一种怎么也搞不懂的赶脚... 博客读了好几篇,代码也动手写了,书中的一些介绍也看了, 各种搜索关于委托的,至今还处于"会用"的阶段. 该怎 ...

  6. 基础知识系列☞Abstract和Virtual→及相关知识

    转载地址→http://www.cnblogs.com/blsong/archive/2010/08/12/1798064.html 在C#的学习中,容易混淆virtual方法和abstract方法的 ...

  7. 学习javascript基础知识系列第二节 - this用法

    通过一段代码学习javascript基础知识系列 第二节 - this用法 this是面向对象语言中的一个重要概念,在JAVA,C#等大型语言中,this固定指向运行时的当前对象.但是在javascr ...

  8. 学习javascript基础知识系列第三节 - ()()用法

    总目录:通过一段代码学习javascript基础知识系列 注意: 为了便于执行和演示,建议使用chrome浏览器,按F12,然后按Esc(或手动选择)打开console,在console进行执行和演示 ...

  9. C# 基础知识系列- 3 集合数组

    简单的介绍一下集合,通俗来讲就是用来保管多个数据的方案.比如说我们是一个公司的仓库管理,公司有一堆货物需要管理,有同类的,有不同类的,总而言之就是很多.很乱.我们对照集合的概念对仓库进行管理的话,那么 ...

随机推荐

  1. Rest Client(Rest接口调试工具,有保存功配置功能) chrome浏览器插件

    Rest Client(Rest接口调试工具,有保存功配置功能) chrome浏览器插件 下载地址 插件的操作很简单,下面是一些简单的实例. 1.安装 在谷歌应用商城搜索postman,如下图1-1所 ...

  2. Mysqldump参数大全(转)

    参数 参数说明 --all-databases  , -A 导出全部数据库. mysqldump  -uroot -p --all-databases --all-tablespaces  , -Y ...

  3. 导出resource文件的的资源

    写个小工具,方便一次性将resource文件中的资源导出,不然反编译后一个个找,真是太麻烦了. using System;using System.Collections.Generic;using  ...

  4. 【gradle】之maven主库找不到Could not find org.restlet.jee:org.restlet:2.1.1

    Could not find org.restlet.jee:org.restlet:2.1.1. 我是用gradle构建solr的时候出现的这个错误,通过google查询到这么一段解释 For th ...

  5. ACL权限设置使用

    acl操作 # 查看操作的分区支不支持acldumpe2fs -h /dev/sda2 | grep aclDefault mount options: user xattr acl 代表支持acl如 ...

  6. 《黄聪:手机移动站SEO优化教程》3、如何禁止百度对PC网站进行自动转码

    视频地址:http://v.youku.com/v_show/id_XNzE2OTM0NzU2.html

  7. CXF发布restful WebService的入门例子(服务器端)

    研究了两天CXF对restful的支持.   现在,想实现一个以 http://localhost:9999/roomservice 为入口, http://localhost:9999/roomse ...

  8. iphone dev 入门实例7:How to Add Splash Screen in Your iOS App

    http://www.appcoda.com/how-to-add-splash-screen-in-your-ios-app/ What’s Splash Screen? For those who ...

  9. C#数字千分位问题

    1.C#中用最简单的方法把数字(不含小数)转换为千分位格式:     如1234567变成1,234,567 方法:1234567.ToString("###,###")   或  ...

  10. spark单机模式简单搭建

    待安装列表hadoophivescalaspark一.环境变量配置:~/.bash_profilePATH=$PATH:$HOME/bin export PATH JAVA_HOME=/usr/loc ...