[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 关于这 ...
随机推荐
- windows 7 安装docker
下载docker-install.exe 下载链接 安装,一路next(安装完成后建议重启电脑) 点击桌面boot2docker Start图标,等待初始化,运行docker --version检验是 ...
- Java面试知多少
1.谈谈&和&&的区别 1.&&是短路判断,在与其他语句一起判断时,第一个条件为假就不判断剩下的条件: & 需要判断所有的条件 2.&是 ...
- POJ 2449 Remmarguts' Date(第k短路のA*算法)
Description "Good man never makes girls wait or breaks an appointment!" said the mandarin ...
- HDU 3062 Party(2-SAT模版题)
Problem Description 有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席.在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是 ...
- <Effective C++>读书摘要--Ctors、Dtors and Assignment Operators<二>
<Item 9> Never call virtual functions during construction or destruction 1.you shouldn't call ...
- thinkphp5学习记录一
1 使用composer安装 composer create-project topthink/think=5.0.* tpblog --prefer-dist 2 配置环境vim /usr/loca ...
- 关于对 NUMA 理解(学习笔记,便于以后查阅)
对NUMA的理解: NUMA是多核心CPU架构中的一种,其全称为Non-Uniform Memory Access,简单来说就是在多核心CPU中,机器的物理内存是分配给各个核的,架构简图如下所示: 每 ...
- Java语言有哪些特点?
1)简单 如果同学们学过C++语言,就会感觉Java眼熟,因为Java中许多基本语句的语法和C++是一样的,像常用的循环语句.控制语句等和C++几乎相同.需要注意的是,Java和C++时两种完全不同的 ...
- Python 断言和异常
Python 断言和异常 Python断言 断言是一种理智检查,当程序的测试完成,可以将其打开或关闭.断言的最简单方法就是把它比作raise-if语句(或更加准确,raise-if-not声明).一个 ...
- [洛谷P4174][NOI2006]最大获利
题目大意:同Petya and Graph,数据范围改成$n\leqslant5\times10^3,m\leqslant5\times10^4$ 题解:同上 卡点:无 C++ Code: #incl ...