[C#] 类型学习笔记三:自定义值类型
既前两篇之后,这一篇我们讨论通过struct 关键字自定义值类型。
在第一篇已经讨论过值类型的优势,节省空间,不会触发Gargage Collection等等。
在对性能要求比较高的场景下,通过struct代替类是不错的选择。
那么,比如我们定义一个Point 类型,里面包含两个左边X, Y。
public struct Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}
是不是这样就OK了呢?
当然不是。因为我们必须尽量避免这个值类型被装箱。
一个良好的值类型的定义,必须充分考虑到这个值类型的使用场景,然后定义好所需要的成员函数,从而避免有的函数调用不到而将值类型装箱的情况。比如说,如果这个Point可能会被放到某个容器中,并且排序,那么Point就必须实现接口System.IComparable,实现CompareTo 方法和接口System.IComprable<T>中类型安全的CompareTo 方法。
老赵前辈的博文防止装箱落实到底,只做一半也是失败 给了一个非常好的例子,我把它引用过来做一点讨论。
博文中的场景是struct所定义的值类型MyKey需要用作字典的键。
我们以System.Collections.Hashtable为例,其构造函数为
public Hashtable(
int capacity,
IEqualityComparer equalityComparer
)
这里面IEqualityComparer 是一个接口,用来作为HashTable的比较器。这个接口包含两个函数:Equals 和 GetHashCode 。
(在System.Collections.Generic.Dictionary,以及其他一些集合的视线中,要求两个对象为了相等,必须具有相同的哈希码——CLR via C# 第三版。所以在很多情况下,Equals 和 GetHashCode都是定义值类型必须重写的两个方法。)
当我们使用struct 定义的值类型来作为HashTable的key时,因为我们自定义的值类型中没有提供Equals 和 GetHashCode的实现,因此值类型被装箱,来调用ValueType的这两个函数。
那么如何实现Equals 和 GetHashCode这两个方法呢?
对于GetHashCode方法,我们使用
public override int GetHashCode() {}
来重写其内容,自定义的计算方式最好能够做到返回的hash值能均匀分布。
对于equals 呢?如果我们仅仅用如下方法是不够的
public override bool Equals(object that) {}
因为它提供的是和object类型的比较,我们真正需要的是和同样类型MyKey的比较。
那么是否再加上这个就够了?
public bool Equals(MyKey that) {}
确实差不多了,但是我们的MyKey需要指明是实现了哪一个接口。程序在运行时,这个接口中的Equals 方法因为在MyKey中被实现,所以才会直接调用MyKey中的 Equals方法。
原文中实现了IEquatable<MyKey>接口。
如果我们打开的Int32的定义看一看
namespace System
{public struct Int32 : IComparable, IFormattable, IConvertible, IComparable<int>, IEquatable<int>
{
........ public override int GetHashCode()
{
return this;
} public override bool Equals(object obj)
{
return obj is int && this == (int)obj;
} public bool Equals(int obj)
{
return this == obj;
}
....
}
}
里面的Equals部分和 MyKey的定义一样,也是有两个实现。同时Int32 实现了IEquatable<int>接口。
相关阅读
[C#] 类型学习笔记三:自定义值类型的更多相关文章
- IOS 学习笔记 2015-03-20 OC-数值类型
一 定义 在Objective-C中,我们可以使用c中的数字数据类型,int.float.long等.它们都是基本数据类型,而不是对象.也就是说,不能够向它们发送消息.然后,有些时候需要将这些值作为对 ...
- python3学习笔记三(数字类型,字符串)
数字(Number)类型 有四种类型:整数.布尔型.浮点数和复数 int整数 bool布尔,如True float浮点数,1.23 complex复数,1+2j.1.2+2.3j 内置的 type() ...
- Java 学习笔记 (三) Java 日期类型
以下内容摘自: https://www.cnblogs.com/crazylqy/p/4172324.html import java.sql.Timestamp; import java.text ...
- Netty学习笔记(三) 自定义编码器
编写一个网络应用程序需要实现某种编解码器,编解码器的作用就是讲原始字节数据与自定义的消息对象进行互转.网络中都是以字节码的数据形式来传输数据的,服务器编码数据后发送到客户端,客户端需要对数据进行解码, ...
- [C#] 类型学习笔记二:详解对象之间的比较
继上一篇对象类型后,这里我们一起探讨相等的判定. 相等判断有关的4个方法 CLR中,和相等有关系的方法有这么4种: (1) 最常见的 == 运算符 (2) Object的静态方法ReferenceEq ...
- [C#] 类型学习笔记一:CLR中的类型,装箱和拆箱
在学习.NET的时候,因为一些疑问,让我打算把.NET的类型篇做一个总结.总结以三篇博文的形式呈现. 这篇博文,作为三篇博文的第一篇,主要探讨了.NET Framework中的基本类型,以及这些类型一 ...
- javascript学习笔记(四) Number 数字类型
数字格式化方法toFixed().toExponential().toPrecision(),三个方法都四舍五入 toFixed() 方法指定小数位个数 toExponential() 方法 用科学 ...
- [读书笔记]C#学习笔记三: C#类型详解..
前言 这次分享的主要内容有五个, 分别是值类型和引用类型, 装箱与拆箱,常量与变量,运算符重载,static字段和static构造函数. 后期的分享会针对于C#2.0 3.0 4.0 等新特性进行. ...
- Hadoop学习笔记—5.自定义类型处理手机上网日志
转载自http://www.cnblogs.com/edisonchou/p/4288737.html Hadoop学习笔记—5.自定义类型处理手机上网日志 一.测试数据:手机上网日志 1.1 关于这 ...
随机推荐
- ElasticSearch 2.0以后的改动导致旧的资料和书籍需要订正的部分
id原先是可以通过path指定字段的 "thread": { "_id" : { "path" : "thread_id" ...
- SpringBoot日志配置(详解) 涉及控制台输出日志、生成日志文件、日志级别修改、hibernate日志不输出
写在前面 本篇主要讲述日志配置,看完本篇可以解决下述问题, 控制台输出日志.生成日志文件.日志级别修改.hibernate日志不输出 Git Demo Path:https://github.com/ ...
- python执行linux命令的两种方法
python执行linux命令有两种方法: 在此以Linux常用的ls命令为例: 方法一:使用os模块 1 2 3 shell# python >> import os >> ...
- js 拼接字符串时,本来想要’#1′ ,返回的却是’#01′
今天在操作一个元素时,id值是拼接的. var index = $(this).attr(‘index’); //0var id = ‘#’ + (index+1); //#01$(id) ...
- 创建、编译、执行 java程序
java源文件(.java)——Java字节码文件(.class)——在java虚拟机上执行 其他语言很多是编译后执行,所以无法跨平台
- lintcode-6-合并排序数组
合并排序数组 合并两个排序的整数数组A和B变成一个新的数组. 样例 给出A=[1,2,3,4],B=[2,4,5,6],返回 [1,2,2,3,4,4,5,6] 挑战 你能否优化你的算法,如果其中一个 ...
- 用glob()函数返回目录下的子文件以及子目录
glob() 函数返回匹配指定模式的文件名或目录 相对于readdir()和opendir()来说,使用glob()函数会方便很多 代码1: <?php function getfilename ...
- Ubuntu编译内核树
什么是内核树?刚开始我也没弄明白,通过这几天的学习,有所感悟,就说说我的理解吧!从形式上看,内核树与内核源码的目录结构形式是相同的,都是由各个层次的文件目录结构组成,但是其中的具体内容肯定是不同的.从 ...
- ismember matlab
ismember 判断A中的元素在B中有没有出现 LIA = ismember(A,B) for arrays A and B returns an array of the same size as ...
- P1667 数列
题目描述 给定一个长度是n的数列A,我们称一个数列是完美的,当且仅当对于其任意连续子序列的和都是正的.现在你有一个操作可以改变数列,选择一个区间[X,Y]满足Ax +Ax+1 +…+ AY<0, ...