一、引言

今天在论坛中看到一位朋友提出这样的一个问题,问题大致(问题的链接为: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. SQL Server 的SQL基础知识

    1.N'关闭'N是指nvarchar,是将其内容关闭作为 Unicode字符常量(双字节).而没有N的 '关闭', 是将关闭作为字符常量(单字节). 平常没有加N,结果里面直接出现?. 具体如下图: ...

  2. UI-动画

    // ------------------UIImageView的动画------------------ // ------------------UIView的动画---------------- ...

  3. Lumen 设置 timezone 时区

    Lumen 设置 timezone 时区 2015-06-19| wid| 后端开发 今天用 Lumen 框架写代码时, 也是初次体验 Lumen, 遇到了一个问题, 从数据库里查出的时间比数据库里保 ...

  4. (转)扩展jquery easyui datagrid 之动态绑定列和数据

    本文转载自:http://blog.csdn.net/littlewolf766/article/details/7336550 easyui datagrid 不支持动态加载列,上次使用的方法是自己 ...

  5. CentOS6.8安装Redis3.2.5

    1.下载Redis3.2.5安装包           wget http://download.redis.io/releases/redis-3.2.5.tar.gz 2.解压.编译.安装redi ...

  6. php接二进制文件

    PHP默认只识别application/x-www.form-urlencoded标准的数据类型. 因此,对型如text/xml 或者 soap 或者 application/octet-stream ...

  7. golang的ssh例子

    package main import ( "github.com/dynport/gossh" "log" ) func MakeLogger(prefix ...

  8. webApi文档好帮手-apidoc使用教程

    来源:http://blog.csdn.net/xumin198908/article/details/41964159 在开发后台接口的过程中,我们肯定要提供一份api接口文档给终端app. 目前大 ...

  9. 【转】SQL SERVER标量表达式的隐式转换

    在SQL Server中的数据类型中,存在着优先级的问题.标量表达示的返回结果类型也会根据操作数的类型而定,如1 +'1'=2.而不是'11',因些Int型的优先级比VARCHAR型的优先级要高.所以 ...

  10. .NET简谈插件系统开发模式

    摘选自[王清培]博客 http://www.cnblogs.com/wangiqngpei557/archive/2011/06/10/2077413.html 今天跟大家分享一下我们在日常开发中并不 ...