既前两篇之后,这一篇我们讨论通过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#] 类型学习笔记一:CLR中的类型,装箱和拆箱

[C#] 类型学习笔记二:详解对象之间的比较

[C#] 类型学习笔记三:自定义值类型的更多相关文章

  1. IOS 学习笔记 2015-03-20 OC-数值类型

    一 定义 在Objective-C中,我们可以使用c中的数字数据类型,int.float.long等.它们都是基本数据类型,而不是对象.也就是说,不能够向它们发送消息.然后,有些时候需要将这些值作为对 ...

  2. python3学习笔记三(数字类型,字符串)

    数字(Number)类型 有四种类型:整数.布尔型.浮点数和复数 int整数 bool布尔,如True float浮点数,1.23 complex复数,1+2j.1.2+2.3j 内置的 type() ...

  3. Java 学习笔记 (三) Java 日期类型

    以下内容摘自:  https://www.cnblogs.com/crazylqy/p/4172324.html import java.sql.Timestamp; import java.text ...

  4. Netty学习笔记(三) 自定义编码器

    编写一个网络应用程序需要实现某种编解码器,编解码器的作用就是讲原始字节数据与自定义的消息对象进行互转.网络中都是以字节码的数据形式来传输数据的,服务器编码数据后发送到客户端,客户端需要对数据进行解码, ...

  5. [C#] 类型学习笔记二:详解对象之间的比较

    继上一篇对象类型后,这里我们一起探讨相等的判定. 相等判断有关的4个方法 CLR中,和相等有关系的方法有这么4种: (1) 最常见的 == 运算符 (2) Object的静态方法ReferenceEq ...

  6. [C#] 类型学习笔记一:CLR中的类型,装箱和拆箱

    在学习.NET的时候,因为一些疑问,让我打算把.NET的类型篇做一个总结.总结以三篇博文的形式呈现. 这篇博文,作为三篇博文的第一篇,主要探讨了.NET Framework中的基本类型,以及这些类型一 ...

  7. javascript学习笔记(四) Number 数字类型

    数字格式化方法toFixed().toExponential().toPrecision(),三个方法都四舍五入 toFixed() 方法指定小数位个数  toExponential() 方法 用科学 ...

  8. [读书笔记]C#学习笔记三: C#类型详解..

    前言 这次分享的主要内容有五个, 分别是值类型和引用类型, 装箱与拆箱,常量与变量,运算符重载,static字段和static构造函数. 后期的分享会针对于C#2.0 3.0 4.0 等新特性进行. ...

  9. Hadoop学习笔记—5.自定义类型处理手机上网日志

    转载自http://www.cnblogs.com/edisonchou/p/4288737.html Hadoop学习笔记—5.自定义类型处理手机上网日志 一.测试数据:手机上网日志 1.1 关于这 ...

随机推荐

  1. windows 7 安装docker

    下载docker-install.exe 下载链接 安装,一路next(安装完成后建议重启电脑) 点击桌面boot2docker Start图标,等待初始化,运行docker --version检验是 ...

  2. Java面试知多少

    1.谈谈&和&&的区别  1.&&是短路判断,在与其他语句一起判断时,第一个条件为假就不判断剩下的条件:   & 需要判断所有的条件  2.&是 ...

  3. POJ 2449 Remmarguts' Date(第k短路のA*算法)

    Description "Good man never makes girls wait or breaks an appointment!" said the mandarin ...

  4. HDU 3062 Party(2-SAT模版题)

    Problem Description 有n对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有1人可以列席.在2n 个人中,某些人之间有着很大的矛盾(当然夫妻之间是没有矛盾的),有矛盾的2个人是 ...

  5. <Effective C++>读书摘要--Ctors、Dtors and Assignment Operators<二>

    <Item 9> Never call virtual functions during construction or destruction 1.you shouldn't call ...

  6. thinkphp5学习记录一

    1 使用composer安装 composer create-project topthink/think=5.0.* tpblog --prefer-dist 2 配置环境vim /usr/loca ...

  7. 关于对 NUMA 理解(学习笔记,便于以后查阅)

    对NUMA的理解: NUMA是多核心CPU架构中的一种,其全称为Non-Uniform Memory Access,简单来说就是在多核心CPU中,机器的物理内存是分配给各个核的,架构简图如下所示: 每 ...

  8. Java语言有哪些特点?

    1)简单 如果同学们学过C++语言,就会感觉Java眼熟,因为Java中许多基本语句的语法和C++是一样的,像常用的循环语句.控制语句等和C++几乎相同.需要注意的是,Java和C++时两种完全不同的 ...

  9. Python 断言和异常

    Python 断言和异常 Python断言 断言是一种理智检查,当程序的测试完成,可以将其打开或关闭.断言的最简单方法就是把它比作raise-if语句(或更加准确,raise-if-not声明).一个 ...

  10. [洛谷P4174][NOI2006]最大获利

    题目大意:同Petya and Graph,数据范围改成$n\leqslant5\times10^3,m\leqslant5\times10^4$ 题解:同上 卡点:无 C++ Code: #incl ...