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. Jenkins项目部署使用教程-----01安装

    基本配置: 1.Linux安装配置jdk环境 1.1.上传到 Linux 服务器:例如: 上传至: cd /usr/local 1.2.解压: rpm -ivh jdk-8u111-linux-x64 ...

  2. JS 节点的属性 与 元素

    节点的属性{     nodeType 是节点的类型:     nodeNam 是节点的名字     nodeValue 节点的值 }可以用节点.属性 取得三个属性的值 节点.nodeType 出来的 ...

  3. Domoticz 中接入斐讯 M1 空气质量检测仪

    前言 M1 是翻车讯出的一款空气质量检测仪,如今斐讯的服务器经常连不上了,M1 不动动手接到 Domoticz 怕是变成摆设了.教程参考了这里和官方的 Using Python plugins. 步骤 ...

  4. 洛谷 P3239 / loj 2112 [HNOI2015] 亚瑟王 题解【期望】【DP】

    ???看不懂的期望DP 题目描述 小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑. 他决定,在脱坑之前,最后再来打一盘亚瑟王.既然是最后一战,就一定要打得漂亮.众所周知,亚 ...

  5. new Date("2018-01-01 11:11:11").valueOf() 在IE下会返回 NaN

    原因是在ie下 new Date不能处理 小横线 这种时间格式,但是 替换成 斜线就可以正常获得毫秒数,像下面这样: new Date(('2018-01-01 11:11:11').replace( ...

  6. npm的介绍

    npm使JavaScript开发人员能够轻松地共享和重用代码,并且可以轻松更新你正在共享的代码. 如果你一直在使用JavaScript,你可能已经听说过npm.npm使JavaScript开发人员能够 ...

  7. 112th LeetCode Weekly Contest Validate Stack Sequences

    Given two sequences pushed and popped with distinct values, return true if and only if this could ha ...

  8. LightOJ - 1197 素数筛

    深夜无事可干啊 #include<bits/stdc++.h> using namespace std; const int maxn = 1e6+11; typedef long lon ...

  9. java8 方法引用与lambda

    List<String> list = new ArrayList<>(); //list.stream().filter((String s)->System.out. ...

  10. springboot(六)-使用shiro

    前提 写之前纠结了一番,这一节放在shiro里面还是springboot里面.后来想了下,还是放springboot里吧,因为这里没有shiro的新东西,只有springboot添加了新东西的使用. ...