1.恒定类型就是一但它们被创建,它们(的值)就是固定的.

恒定类型可以很好的在基于哈希代码的集合上工作。以Object.GetHashCode()方法返回的值,对同一个实例是必须相同的

2.一个客户类型就不是原子类型;它是由多个不同的恒定的组成部份构成的:地址,名字以及一个电话号码集合。

3. 可变类型:书中举出的例子为地址Address结构的公共属性中提供了set方法。

推荐做法:

  1. public struct Address
  2. {
  3. private readonly string _line1;
  4. private readonly string _line2;
  5. private readonly string _city;
  6. private readonly string _state;
  7. private readonly int _zipCode;
  8. //移除所有的属性设置功能
  9. public string Line1 { get { return _line1; } }
  10. public string Line2 { get { return _line2; } }
  11. public string City { get { return _city; } }
  12. //etc
  13.  
  14. //使用构造函数初始化对象
  15. public Address(string line1, string line2, string city, string state, int zipCode)
  16. {
  17. _line1 = line1;
  18. _line2 = line2;
  19. _city = city;
  20. _state = state;
  21. _zipCode = zipCode;
  22. ValidateState(state);
  23. }
  24. }

使用:

  1. // Create an address:
  2. Address a1 = new Address( "111 S. Main", "", "Anytown", "IL", 61111 );
  3. // To change, re-initialize:
  4. a1 = new Address( a1.Line1, a1.Line2, "Ann Arbor", "MI", 48103 );

  这正是期望的安全性:a1要么是默认的原始值,要么是新的值。如果在构造对象时发生了异常,那么a1保持原来的默认值不变。

.Net里的日期时间结构,它就是一个典型的恒定常量例子。它没有提供任何的对单独年,月,日或者星期进行修改的方法。因为单独修改其中一个,可能导致整个日期处于不正确的状态。

为了创建一个恒定类型,你须要确保你的用户没有任何机会来修改内部状态。

  1. 值类型不支持派生类所以不必定义担心派生类来修改它的内部状态。
    要注意任何在恒定类型内的可变的引用类型字段。当你为这些类型实现了构造函数后,你须要被动的把可变的引用类型COPY一遍

  举例:不推荐如下写法,原因是PhoneList内部引用的数组,引用了分配在对象外的数组存储空间上。开发人员可通过另一个引用到这个存储空间上的对象来修改你的恒定结构

  1. public struct PhoneList
  2. {
  3. private readonly Phone[] _phones;
  4. public PhoneList(Phone[] ph)
  5. {
  6. _phones = ph; //注意
  7. }
  8. }
  9. Phone[] phones = new Phone[];
  10. PhoneList pl = new PhoneList( phones );
  11. // Modify the phones also modifies the pl 注意
  12. phones[] = Phone.GeneratePhoneNumber( );

  而是这种方案

  1. public struct PhoneList
  2. {
  3. private readonly Phone[] _phones;
  4. public PhoneList(Phone[] ph)
  5. {
  6. _phones = new Phone[ ph.Length ];
  7. // Copies values because Phone is a value type. 注意比较
  8. ph.CopyTo( _phones, );
  9. }
  10. }
  11. Phone[] phones = new Phone[];
  12. PhoneList pl = new PhoneList( phones );
  13. // Modify the phones Does not modify the copy in pl. 注意
  14. phones[] = Phone.GeneratePhoneNumber( );

  

EffectiveC#7--选择恒定的原子值类型数据的更多相关文章

  1. EffectiveC#6--区别值类型数据和引用类型数据

    1. 设计一个类型时,选择struct或者class是件简单的小事情,但是,一但你的类型发生了改变, 对所有使用了该类型的用户进行更新却要付出(比设计时)多得多的工作. 2.值类型:无多态但性能佳. ...

  2. EffectiveC#8--确保0对于值类型数据是有效的(初始化问题)

    1.决不要创建一个不包括0在内的枚举类型 2.举例如下: public enum Planet { Mercury = 1, Venus = 2, Earth = 3, Mars = 4, Jupit ...

  3. Symbol ES6 新增的一种值类型数据,表示一种绝不重复的值

    let s1 = Symbol(33); let s2 = Symbol(33); alert(typeof(s1)); //数据类型判断 // alert(s1.toString()); //可把一 ...

  4. CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段

    编程语言的基元类型   某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32();  // a = 0 a = 1 ...

  5. [CLR via C#]5.3 值类型的装箱和拆箱

    原文:[CLR via C#]5.3 值类型的装箱和拆箱 在CLR中为了将一个值类型转换成一个引用类型,要使用一个名为装箱的机制. 下面总结了对值类型的一个实例进行装箱操作时内部发生的事: 1)在托管 ...

  6. C#中的基元类型、值类型和引用类型

    C# 中的基元类型.值类型和引用类型 1. 基元类型(Primitive Type) 编译器直接支持的类型称为基元类型.基元类型可以直接映射到 FCL 中存在的类型.例如,int a = 10 中的 ...

  7. CLR via 笔记 5.3 值类型的装箱和拆箱

    1.装箱 为了将一个值类型转换成一个引用类型,要使用一个名为装箱(Boxing)的机制. 1.在托管堆中分配好内存.分配的内存量是值类型的各个字段需要的内存量加上托管堆的所有对象都有的两个额外成员(类 ...

  8. JavaScript数据类型--值类型和引用类型

    值类型:也称为原始数据或原始值(primitive value). 这类值存储在栈(stack)中,栈是内存中一种特殊的数据结构,也称为线性表,栈按照后进先出的原则存储数据,先进入的数据被压入栈底,最 ...

  9. C#基础知识系列二(值类型和引用类型、可空类型、堆和栈、装箱和拆箱)

    前言 之前对几个没什么理解,只是简单的用过可空类型,也是知道怎么用,至于为什么,还真不太清楚,通过整理本文章学到了很多知识,也许对于以后的各种代码优化都有好处. 本文的重点就是:值类型直接存储其值,引 ...

随机推荐

  1. gstreamer让playbin能够播放rtp over udp流数据

    最近一段时间在研究传屏低延迟传输相关的一些东西.本来想使用gstreamer来验证下rtp over udp传送h264 nal数据相关 的,结果发现竟然不能用playbin来播放rtp的数据!诚然, ...

  2. alt和title的用法区别

    经常用到这两个属性,但是一直没有总结他们的区别.现在我对他们两个的用法做一下总结: 相同点:他们都会飘出一个小浮层,显示文本内容. 不同点: 1.alt只能是元素的属性,而title即可以是元素的属性 ...

  3. VC++ try catch (转)

    VC++ try catch (转)   以前都是用try{} catch(-){}来捕获C++中一些意想不到的异常, 今天看了Winhack的帖子才知道,这种方法在VC中其实是靠不住的.例如下面的代 ...

  4. 【JAVA编码专题】深入分析 Java 中的中文编码问题

    http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/ 几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么 ...

  5. ASP转PHP手记

    打算将动易网站管理系统移植到PHP环境中,寻寻觅觅了很多PHP内容管理网站,发现网上有动易转PHPCMS的代码,所以就拿定注意用PHPCMS的在google上找到一转换程序,动手做来还成功了,现将此次 ...

  6. python functools.wraps装饰器模块

    # -*-coding=utf-8 -*-#实现一个函数执行后计算执行时间的功能 __author__ = 'piay' import time, functools def foo(): ''' 定 ...

  7. [C入门 - 游戏编程系列] 贪吃蛇篇(五) - 蛇实现

    因为已经写了食物的实现,所以我不知道到底是该先写世界的实现还是蛇的实现.因为世界就是一个窗口,可以立刻在世界中看到食物的样子,对于大多数人来说,如果写完代码立刻就能看到效果,那就再好不过了.可是,我最 ...

  8. libevent使用之安装(一)

    1.下载安装包,在官网http://www.monkey.org/~provos/libevent/下载 2.解压 运行命令: tar zxvf libevent-2.0.10-stable.tar. ...

  9. IOS回调机制——代理,通知中心以及Block

    Xcode5.0正式版 IOS7和Xcode5正式版在昨天正式可以下载.IOS7不多说了,交互设计,界面风格,操作的简化程度都属于比较领先的水平. 这里来说说Xcode5正式版,和以前的Xcode5测 ...

  10. Compound class names are not supported. Consider searching for one class name and filtering the results

    原文地址:http://stackoverflow.com/questions/20361643/compound-class-names-are-not-supported-consider-sea ...