1.重写GetHashCode方法注意点:

(1)重写GetHashCode方法,也应重写Equals方法,否者编译器会警告。

(2)相等的对象必须有相等的散列码(若a.Equals(b),则a.GetHashCode()==b.GetHashCode())。

(3)GetHashCode()不应引发任何异常,GetHashCode()必须总是成功的返回一个值。

(4)散列码应该尽可能的保持唯一。

(5)GetHashCode()的性能应该优化,GetHashCode()通常在Equals()实现中用于“短路”一次完整的相等性比较(假如散列码不同,当然就没有必要进行完整的相等性比较了),所以当类型作为字典集合中的键类型使用时,会频繁地调用这个方法。

(6)针对一个特定的对象,在这个对象的生存期内,GetHashCode()始终应该返回相同的值,即使对象的数据发生了改变。在许多时候,应该缓存方法的返回值,从而确保这一点。

  Other:我们通常采取的做法是为来自相应类型的散列码应用XOR(异或)运算符,并确保XOR的操作数不相近或相等,否则结果会全是零。在操作数相近或相等的情况下,考虑使用移位和加法操作。其他的备选运算符--AND和OR--具有类似的限制,这些限制会发生的更加频繁,多次使用AND会逐渐变成全为0;而多次应用OR会逐渐变成全为1。为了进行更细致的控制,应该使用移位运算符来分解一个比int大的类型。例如,假定有一个名为value的long类型,它的GetHashCode()方法可以像下面这样实现:int GetHashCode(){return (int)value ^ (int)(value >> 32)}。

2.在object中,Equals()这个virtual方法的实现是用ReferenceEquals()来评判相等性。因为这个实现往往都是不充分,所以一般都有必要重写Equals()方法。

3.重写Equals()方法注意点,:

(1)检查是否为null;

(2)如果是引用类型,就检查引用是否相等;

(3)可能要检查散列码是否相等,如果散列码不相等,就没有必要继续执行一次全面的、逐字段的比较。(相等的两个对象不可能散列码不同)

(4)比较每一个标识字段,判断是否相等。

4.相等性实现的指导原则:

(1)Equals()、==运算符和!=运算符应该一起实现;

(2)一个类型在Equals()、==和!=实现中应该使用相同的算法;

(3)实现Equals()、==和!=时,也应实现一个类型的GetHashCode()方法;

(4)GetHashCode()、Equals()、==和!=永远不能引发异常;

(5)实现IComparable时,与相等性有关的方法也应实现;

可以查看Coordinate类的定义便于直观了解。

5.其他二元运算符(如“+、-、&”)的定义:就像“==”定义一样,其中至少有一个参数的类型是本类型(当前重载运算符的类型)。在重定义了这些二元运算符后,就可以像操作基本的数值类型一样进行运算。可查看Coordinate类。

6.其他的一元运算符(如“+正、-负、!、true、false”)的重载与重载二元运算符类似,只是重载“true、false”要成对出现,重载的参数变成了一个。其中的“true、false”运算符主要应用与if、do...while、for这些控制表达式使用。

7.转型运算符:转型运算符分为显式(explicit)与隐式(implicit),隐式转型总是成功,显式转型提醒用户这是不希望的行为,显式存在2个问题“①转换可能会有异常,②转换可能会存在部分数据丢失”。可查看Angle结构的代码示例。

8.命名空间:命名空间可以嵌套,就是类一样可以嵌套,命名空间的嵌套有2种,分别为声明层次的嵌套;声明时“.”符号隔开。如 System.IO。

9.生成类文件的注释的xml文档:可以在VS的命令工具中使用“csc /doc:文档名.xml 类文件”。其实也可以在VS-IDE的项目属性=>生成=>设置xml文档输出,即可生成项目文档说明,当然可以使用一些免费工具进行文档生成(如GhostDoc、NDoc)。在把程序集提供给他人使用时(程序集是不含文档说明,编译器会把源代码中注释忽略),若要使VS IntelliSense提示程序集中的成员说明信息,需让XML文件的文件名与您要支持的程序集相同,确保XML文件与程序集位于同一个目录中,从而在Visual Studio项目中引用程序集时,也可以找到.xml文件。

10.终结器:终结器是用来清理一个类的占用的昂贵的资源(如数据库连接、文件句柄),其不能显式调用,是由垃圾回收器负责调用,因此我们不能在编译时确定终结器执行的时机,唯一确定的是终结器会在上一次使用对象之后,并在应用程序关闭之前的某个时间运行。其声明的方式是“~类名(){}”,不允许传递参数与添加如public修饰符,因为其本身是不能显式调用。基类中的终结器会作为对象终结调用的一部分而自动调用。可查看TemporaryFileStream类的处理代码。

11.使用using语句进行确定性的终结:终结器本身的问题在于,它们不支持一个确定性终结(也就是预知一个终结器的运行时间的能力),相反,终结器是作为对资源清理的一个备用机制来使用。假如开发者忘记显式调用必要的清理代码,就可以依赖终结器来清理资源。要进行确定的终结需要类本身实现IDisposable接口,该接口内包含Dispose()方法,需要自己实现具体的细节来清理资源。使用using语句终结和使用try-finally处理是一个效果,因为此处的using语句在最终生成的CIL代码上就是try-finally,using语句只是提供了try-fianlly块的一个语法快捷方式。在using中可以实例化多个类型一致的变量,来一起处理释放。可查看TemporaryFileStream类的处理代码。

12.资源利用与终结的指导原则:

(1)只有在对象使用了稀缺或昂贵资源的前提下,才为对象实现finalize,终结会推迟垃圾回收。

(2)有终结器的对象应该实现IDisposable接口来支持确定性的终结。

(3)终结方法通常调用与IDisposable调用相同的代码。

(4)终结器应避免造成任何未处理的异常。

(5)像Dispose()和Close()这样的确定性终结方法应该调用GC.SuppressFinalize(),使垃圾回收更快的发生。

(6)资源清理方法应该足够简单,而且只应着重于清理由终结实例引用的资源。

(7)若基类实现了Dispose(),则派生实现应调用基类的实现。

13.延迟初始化Lazy<T>:在.net4.0中提供了Lazy<T>可对对象进行延迟初始化(即需要该对象时才被创建),可查看DataCache类的实现。

public class Coordinate
{
/// <summary>
/// 经度
/// </summary>
public Angle Longitude { get; set; }
/// <summary>
/// 维度
/// </summary>
public Angle Latitude { get; set; } public override int GetHashCode()
{
int hashCode = Longitude.GetHashCode();
if (hashCode != Latitude.GetHashCode())
{
hashCode ^= Latitude.GetHashCode();
}
return hashCode;
} public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
return Equals((Coordinate)obj);
} public bool Equals(Coordinate obj)
{
if (obj == null)
{
return false;
}
if (GetHashCode() != obj.GetHashCode())
{
return false;
}
return Longitude.Equals(obj.Longitude) && Latitude.Equals(obj.Latitude);
} public static bool operator ==(Coordinate one, Coordinate two)
{
if (ReferenceEquals(one, null))//此处不用==判断null,是因为我们重定义了本类的“==”操作符,否则会进入递归造成死循环。
{
return ReferenceEquals(two, null);
}
return one.Equals(two);
} public static bool operator !=(Coordinate one, Coordinate two)
{
return !(one == two);
} public static Coordinate operator +(Coordinate one, Coordinate two)
{
return new Coordinate()
{
Longitude = one.Longitude + two.Longitude,
Latitude = one.Latitude + two.Latitude
};
} public static bool operator !(Coordinate one)
{
return false;
} public static bool operator true(Coordinate one)
{
return one.Latitude.Hours > && one.Latitude.Minutes > && one.Latitude.Seconds > ;
} public static bool operator false(Coordinate one)
{
if (one)
{
return false;
}
return true;
}
} public struct Angle
{
public Angle(int hours, int minutes, int seconds)
{
Hours = hours;
Minutes = minutes;
Seconds = seconds;
}
public int Hours { get; set; }
public int Minutes { get; set; }
public int Seconds { get; set; } public Angle Move(int hours, int minutes, int seconds)
{
return new Angle(Hours + hours, Minutes + minutes, Seconds + seconds);
} public override int GetHashCode()
{
return base.GetHashCode();
} public override bool Equals(object obj)
{
return Equals((Angle)obj);
} public bool Equals(Angle obj)
{
return Hours == obj.Hours && Minutes == obj.Minutes && Seconds == obj.Seconds;
} public static Angle operator +(Angle one, Angle two)
{
return one.Move(two.Hours, two.Minutes, two.Seconds);
} public static implicit operator string(Angle one)
{
return string.Format("{0},{1},{2}", one.Hours, one.Minutes, one.Seconds);
} public static explicit operator Angle(string text)
{
try
{
var result = text.Split(',').Cast<int>();
return new Angle(result.ElementAt(), result.ElementAt(), result.ElementAt());
}
catch (Exception ex)
{
throw ex;
}
}
} public class TemporaryFileStream : IDisposable
{
public TemporaryFileStream(string fileName)
{
//todo
} ~TemporaryFileStream()
{
Dispose();
} private readonly FileStream _stream;
public FileStream Stream
{
get { return _stream; }
} private readonly FileInfo _file;
public FileInfo File
{
get { return _file; }
} public void Dispose()
{
Stream?.Close();
File?.Delete();
/*该语句的作用是从终结列队中移除TemporaryFileStream类实例,一个对象在终结列队中就是不会进行垃圾回收,必须终结后才能垃圾回收,执行此语句就不会推迟该对象的
垃圾回收。*/
GC.SuppressFinalize(this);
}
} public class DataCache
{
public DataCache()
{
_fileStream = new Lazy<TemporaryFileStream>(() => new TemporaryFileStream(FileStreamName));
}
public string FileStreamName { get; set; } private Lazy<TemporaryFileStream> _fileStream;
public TemporaryFileStream FileStream
{
//只有在返回“value”时,才会执行“() => new TemporaryFileStream(FileStreamName)”代码,
get { return _fileStream.Value; }
} /* .net4.0以前模拟的延迟初始化对象
private TemporaryFileStream _fileStream;
public TemporaryFileStream FileStream
{
get
{
if (_fileStream == null)
{
_fileStream = new TemporaryFileStream(FileStreamName);
}
return _fileStream;
}
}*/
}

------------------------以上内容根据《C#本质论 第三版》进行整理

C#学习笔记7的更多相关文章

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  3. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  4. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  5. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  6. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  7. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  8. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

  9. DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记

    今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...

  10. ucos实时操作系统学习笔记——任务间通信(消息)

    ucos另一种任务间通信的机制是消息(mbox),个人感觉是它是queue中只有一个信息的特殊情况,从代码中可以很清楚的看到,因为之前有关于queue的学习笔记,所以一并讲一下mbox.为什么有了qu ...

随机推荐

  1. uC/OS-II 一些函数简介

    获得更多资料欢迎进入我的网站或者 csdn或者博客园 以前搞硬件的经验,最近突然翻出来了.分享给大家:主要讲解uC/OS-II常用函数:虽说现在转行软件了,但是感觉之前搞硬件的经验还真是很有用对于理解 ...

  2. Python之freshman07 面向对象编程jinjie

    本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程 经典类vs新式类 把下面代码 ...

  3. node.js express 启用 https

    服务端和客户端各有一对公钥和私钥,使用公钥加密的数据只能用私钥解密,建立https传输之前,客户端和服务端互换公钥.客户端发送数据前使用服务端公钥加密,服务端接收到数据后使用私钥解密,反之亦如此. 公 ...

  4. 教你搭建SpringMVC框架( 附源码)

    一.项目目录结构 二.SpringMVC需要使用的jar包 commons-logging-1.2.jar junit-4.10.jar log4j-api-2.0.2.jar log4j-core- ...

  5. P3813 [FJOI2017]矩阵填数

    传送门 矩阵很大,但是发现 $n$ 很小,从这边考虑,对于一个一堆小矩阵放在一起的情况 考虑把每一块单独考虑然后方案再乘起来 但是这些奇怪的东西很不好考虑 所以暴力一点,直接拆成一个个小块 但是这样我 ...

  6. Python-list()之remove()/pop() I /del()

    代码块 remove #remove删除首个符合条件的元素,并不删除特定的索引. n =[1,2,2,3,4,5] n.remove(3) print (n) #输出 [1, 2, 2, 4, 5] ...

  7. D3.js v4版本 按住shift键框选节点demo

    http://download.csdn.net/download/qq_25042329/10139649

  8. Apache Shiro(二)-登录认证和权限管理数据库操作

    数据库支持 在上一篇中使用ini 配置文件进行了相关权限数据的配置. 但是实际工作中,我们都会把权限相关的内容放在数据库里. 所以本知识点讲解如何放在数据库里来撸. RBAC 概念 RBAC 是当下权 ...

  9. mysql命令查询表的个数

    https://blog.csdn.net/xiao__ge/article/details/56671221 语句如下: SELECT count(TABLE_NAME) FROM informat ...

  10. webAPI过滤器返回数据加密

    项目需求: 接口返回的数据,存在一些敏感信息,不希望其他用户看到,将Data进行加密传输 代码如下: public class EncryptDataFilterAttribute : ActionF ...