C#类型都派生自System.Object

祖先的优良传统:Object的公共方法

Equals: 对象的同一性而非相等性

GetHashCode:返回对象的值的哈希码

ToString:默认返回类型的完整名称 this.GetType().FullName

GetType:返回从Type派生的一个对象的实例,即对象的元数据信息,此方法为非虚方法,为防止类来重写该方法,隐瞒真实的类型信息,从而破坏类型的安全性

GetHashCode有什么用?

判断对象是否相等的快速检查。Equals方法和GetHashCode方法的重写应该同时存在。如果Equals方法返回的结果是true,那么GetHashCode方法返回的结果应该相同。如果GetHashCode方法返回的结果相同,那么Equals方法返回的结果不一定是true。

public class Student
{
public string FirstName { get; private set; }
public string LastName { get; private set; } public Student(string firstName, string lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
} public override bool Equals(object obj)
{
Console.WriteLine("Called Equals");
if (obj == null || this.GetType() != obj.GetType())
return false;
return this.FirstName == ((Student)obj).FirstName
&& this.LastName == ((Student)obj).LastName;
} public override int GetHashCode()
{
Console.WriteLine("Called GetHashCode");
return this.FirstName.GetHashCode();
}
} static void Main(string[] args)
{ Student student1 = new Student("Jun", "Lei");
Student student2 = new Student("Kaifu", "Li");
Student student3 = new Student("Jun", "Zhu"); //第一次调用
var dic = new Dictionary<Student, object>();
dic[student1] = new object();
Console.WriteLine("==================");
Console.WriteLine(dic.ContainsKey(student2));
Console.WriteLine("==================");
Console.WriteLine(dic.ContainsKey(student3));
//第二次调用
Student student4 = new Student("Jun", "Lei");
var dic1 = new Dictionary<Student, object>();
dic1[student4] = new object();
Console.WriteLine("==================");
Console.WriteLine(dic1.ContainsKey(new Student("Jun", "Lei"))); } 

说明:在上面的Student类中我们重写了Equals和GetHashCode这两个基类的方法,在针对Dictionary这种散列值的key值判断的时候系统默认先调用GetHashCode判断,然后再掉用Equals方法判断,微软约定如果两个对象的哈希码不一样,则两个对象肯定不相等。所以在判断对象相等时系统默认先调用此方法做最简单的判断。举个例子:要比较两个人是不是兄弟,第一眼肯定是看两个人的性别是否相同(GetHashCode),如果性别都不一样,肯定不是兄弟,然后再判断长相,血型,DNA等的相似性(Equals)。

上述代码第一次调用时,输出结果如下:

在Student中我们重写了GetHashCode方法,让它获取FirstName的哈希值,这也就是意味着如果两个Student的FirstName相同的话这两个对象判断相等的时候系统默认返回的哈希值将是一样的,我们可以看到student1和student2 对象中的每一个字段都不相同,所以根绝GethashCode直接判断不相等,所以系统直接返回false,没有调用Equals方法判断。而Student3对象和Student1对象的FirstName是一样的,所以感觉哈希值已经判断不出来了,所以又调用了一次Equals方法进行深入判断,由于LastName不一样,所以返回结果为false。由上述代码我们可以得出结论,系统判断对象相等性的时候先调用GetHashCode判断,如果对象的哈希值一样,再根据Equals的实现判断,否则直接返回false。

如果我们把GetHashCode的实现注释掉,直接用系统的方法的话,返回结果如下:

因为Student1和Student3是两个不同的对象,所以哈希码肯定不一样,所以就不会调用Equals方法再继续进行判断了

基元类型

基元类型:编译器直接支持的数据类型称之为基元类型,它直接映射到Framework类库(FCL)中存在的类型,比如 int  —> System.Int32

int a = 0;   //最方便的语法
System.Int32 a = 0 ; //方便的语法
int a = new int() ; //不方便的语法
System.Int32 a = new System.Int32(); //最不方便的语法  

问题1:以上四行代码生成的IL代码完全一样吗 ?(完全一样,可以根据生成的IL代码判断)

问题2:在32位操作系统上运行时,int代表32位整数,在64位操作系统上运行时,int代表64位整数这种说法正确吗?(完全错误,不管在什么操作系统上都是代表32位整数)

下面是C#中的基元类型和FCL中类型的对应关系

引用类型:

a.内存分配到托管堆上

b.托管堆上分配的每个对象都会包含:对象本身的值,类型对象指针,同步索引块

c.对象传递的是内存的引用地址

d.没有被使用的情况下,会被垃圾回收

eg:类都是引用类型,string

值类型:

a.内存分配到它声明的地方

b.分配的内存只包含本身的值

c.传递的是值本身

d.不会被垃圾回收

e.所有值类型都是隐式封闭的 sealed(防止一个值类型用作其他类型的基类型)

f.所有值类型都是 System.ValueType 的后代

eg: int , decimal , double, struct

关于引用类型的类型对象指针和同步索引块,下面的博客将的很详细,不过我还是没有完全理解,所有在此不做详细解释。

类型对象指针和同步索引块:http://www.cnblogs.com/yuyijq/archive/2009/03/13/1410071.html

Code1:

string str = "ab";
string str1 = str;
str = "abc";
str1 = ?  

上面代码你一眼看过去肯定以为str1会输出 abc ,因为是引用类型啊,我们改了引用的值之后它也会跟这边,因为引用的是同一片内存地址呀。如果真这样认为那我只能说太年轻了。

输出依然是 ab,具体原因如下:

String的不可变性:string 对象是只读的,一旦创建了该对象,就不能修改该对象的值。看来似乎修改了,实际是string经过了特殊处理,每次改变值时都会建立一个新的string对象,变量会指向这个新的对象,而原来的还是指向原来的对象,所以不会改变。这也是string效率低下的原因,如果经常改变string的值则应该使用StringBuilder而不使用string

StringBulider: 通过分配一个缓存(工作区)来解决这些问题,在工作区中对字符串应用StringBuilder类的相关方法。包括添加,删除,移除,插入和替换字符等等。执行完之后,将调用ToString方法把工作区中的内容转换为一个字符串,方便赋给一个字符串变量。这样StringBuilder会提升一些性能。

Code2:

string  str1 = "string" ;
string str2 = "string" ;
Console .WriteLine(string .ReferenceEquals(str1, str2));  

我们虽然初始化了两个字符串对象,看起来是分配了两个内存地址,但其实不是的,CLR对此作了优化,具体解释如下:

当CLR初始化的时,会创建一个内部的散列表,Key为字符串,Value为指向托管堆中字符串对象的引用。当构造str1时,先会去散列表中查询是否存在”string”字符串,如果不存在那么会在托管堆中构造一个新的String对象,然后将”string”字符串和指向该对象的引用添加到散列表中,当构造str2时,由于散列表中存在 Key为”string”的引用,于是将Value值赋值给str2,那么str1和str2引用的是同一个String对象

注意:string 是不可变的引用的类型,CLR在运行时进行了优化,相同的string实际上在内存中只存在一份

Code3:

 public struct Point
{
public int x = 0;
public int y = 0;
}  

上面的代码是编译不通过的,原因是:

值类型不支持无参数构造函数,当一个值类型没有提供任何有参构造函数的时候,是不能够对字段在定义中进行初始化。

为什么微软不支持值类型的无参构造函数?

防止开发人员不去显式调用构造函数,对于值类型的变量来说,如果不去显式调用构造函数的话,编译器不会在生成的IL代码中添加调用构造函数的代码的。

C# 类型基础(上)的更多相关文章

  1. 《C#从现象到本质》读书笔记(二)第2章 C#类型基础(上)

    <C#从现象到本质>读书笔记第二篇 第2章 C#类型基础(上) 类型指的是集合{类,结构,接口,枚举,委托}中的任意一个成员.任何拥有某类型的值(value)称为某类型的一个实例(inst ...

  2. C#学习笔记——面向对象、面向组件以及类型基础

    C#学习笔记——面向对象.面向组件以及类型基础 目录 一 面向对象与面向组件 二 基元类型与 new 操作 三 值类型与引用类型 四 类型转换 五 相等性与同一性 六 对象哈希码 一 面向对象与面向组 ...

  3. 在Livemedia的基础上开发自己的流媒体客户端

    一.背景 二.Livemedia框架介绍 1.总体框架 2.客户端框架 2.1 客户端openRTSP流程 2.2增加一种新的媒体 2.2.1增加媒体的format 2.2.2 新媒体需要考虑的问题 ...

  4. 使用mysqlbinlog工具的基础上及时恢复数据的位置或点

    使用mysqlbinlog工具的基础上及时恢复的位置或点 MySQL备份一般采取完全备份的形式加日志备份.让我们运行一个完整备份,每天.每小时运行二进制日志备份. 这样在MySQL Server故障后 ...

  5. [CLR via C#]4. 类型基础及类型、对象、栈和堆运行时的相互联系

    原文:[CLR via C#]4. 类型基础及类型.对象.栈和堆运行时的相互联系 CLR要求所有类型最终都要从System.Object派生.也就是所,下面的两个定义是完全相同的, //隐式派生自Sy ...

  6. UNIX基础上

    时光飞逝,转眼已经毕业快2年了,觉得自己学的东西多却不精.对此深深的思考一下,觉得有必要连载unix环境编程文章,以此激励自己学习.在此立贴为证,2天一篇博客从零开始阐述unix的环境编程. 参考书籍 ...

  7. 如何基于Winform开发框架或混合框架基础上进行项目的快速开发

    在开发项目的时候,我们为了提高速度和质量,往往不是白手起家,需要基于一定的基础上进行项目的快速开发,这样可以利用整个框架的生态基础模块,以及成熟统一的开发方式,可以极大提高我们开发的效率.本篇随笔就是 ...

  8. 《C#从现象到本质》读书笔记(三)第3章C#类型基础(下)

    <C#从现象到本质>读书笔记第3章C#类型基础(下) 常量以关键字const修饰.C#支持静态字段(类型字段)和实例字段. 无参属性的get方法不支持参数,而有参属性的get方法支持传入一 ...

  9. [No0000B9]C# 类型基础 值类型和引用类型 及其 对象复制 浅度复制vs深度复制 深入研究2

    接上[No0000B5]C# 类型基础 值类型和引用类型 及其 对象判等 深入研究1 对象复制 有的时候,创建一个对象可能会非常耗时,比如对象需要从远程数据库中获取数据来填充,又或者创建对象需要读取硬 ...

  10. [No0000B5]C# 类型基础 值类型和引用类型 及其 对象判等 深入研究1

    引言 本文之初的目的是讲述设计模式中的 Prototype(原型)模式,但是如果想较清楚地弄明白这个模式,需要了解对象克隆(Object Clone),Clone其实也就是对象复制.复制又分为了浅度复 ...

随机推荐

  1. Jeecg踩坑不完全指南

    公司用了这个叫做jeecg的快速开发框架,我不知道有多少公司在用这个框架,园子里有的可以吱一声.个人觉得这框架唯一优势就是可以让不会ssh的人也能进行开发,只要你会J2SE,有web后台发开经验即可. ...

  2. ElasticSearch 集群监控

    要监控哪些 ElasticSearch metrics? Elasticsearch 提供了大量的 Metric,可以帮助您检测到问题的迹象,在遇到节点不可用.out-of-memory.long g ...

  3. border-image详解

    一.border-image的兼容性 border-image可以说是CSS3中的一员大将,将来一定会大放光彩,其应用潜力真的是非常的惊人.可惜目前支持的浏览器有限,仅Firefox3.5,chrom ...

  4. int ,long long等范围

    unsigned   int   0-4294967295   int   -2147483648-2147483647 unsigned long 0-4294967295long   -21474 ...

  5. 久未更 ~ 一之 —— 关于ToolBar

    很久没更博客了,索性开一个久未更 系列 > > > > > 久未更 系列一:关于ToolBar的使用(后续补充) //让 ToolBar 单独使用深色主题 使得 tool ...

  6. Redis能干啥?细看11种Web应用场景

    下面列出11种Web应用场景,在这些场景下可以充分的利用Redis的特性,大大提高效率. 1.在主页中显示最新的项目列表. Redis使用的是常驻内存的缓存,速度非常快.LPUSH用来插入一个内容ID ...

  7. fsockopen — 打开一个网络连接或者一个Unix套接字连接

    fsockopen (PHP 4, PHP 5, PHP 7) 说明 resource fsockopen ( string $hostname [, int $port = -1 [, int &a ...

  8. 邓_ Jqery·笔记本【照片】

    -------------------------------------------------------------------------------------------- [PHP] - ...

  9. hql(Hibernate Query Language)

    1.Criteria查询对查询条件进行了面向对象封装,符合编程人员的思维方式,不过HQL(Hibernate Query Language)查询提供了更加丰富的和灵活的查询特性,因此Hibernate ...

  10. 安利一个神器:Tmux

    对于程序员来说,一个好用且高效的软件工具就如同加持了神技的游戏角色.下面就给大家介绍一个神器 Tmux 以及个人的使用总结. 一.我所认识的 Tmux 在工作中,我把 tmux 当作终端会话管理器来使 ...