10.1 无参属性

10.1.1 自动实现的属性

10.1.2 合理定义属性

  • 属性可以只读或只写,而字段访问总是可读和可写的(一个例外是 readonly 字段仅在构造器中可写).
  • 属性方法可能抛出异常;字段访问永远不会.
  • 属性不能作为 out 或 ref 参数传给方法,而字段可以.
  • 属性方法可能花较长时间执行,字段访问则总是立即完成.线程同步不要使用属性,而用方法.从MashalByRefObject派生的类永远都不应该使用属性.
  • 连续多次调用,属性方法每次都可能返回不同的值,字段则每次都返回相同的值.
  • 属性方法可能造成明显的副作用(不同的赋值顺序,可能会出现不同的行为),字段访问则永远不会.
  • 属性方法可能需要额外的内存,或者返回的引用并非指向对象状态一部分,造成对返回对象的修改作用不到原始对象身上.

10.1.3 对象和集合初始化器

  1. String s= new Employee (){ Name="Jeff", Age=45 }.ToString().ToUpper();
  2. //如果想调用的本来就是一个无参构造器,c#还允许省略起始大括号之前的圆括号.
  3. String s= new Employee { Name="Jeff", Age=45 }.ToString().ToUpper();

10.1.4 匿名类型

  1. var o1=new{ Name="Jeff", Year=1964};
  2. Console.WriteLine("Name={0},Year={1}",o1.Name,o1.Year);
  3. //或
  4. String Name="Grant";
  5. DateTime dt= DateTime.Now;
  6. //有两个属性的一个匿名类型
  7. //1.String Name 属性设为"Grant"
  8. //2.Int32 Year 属性设为dt中的年份
  9. var o2 = new { Name, dt.Year };
  10. Console.WriteLine("Name={0},Year={1}",o2.Name,o2.Year);
  • 如果源代码中定义了多个匿名类型,且这些类型具有相同的结构,编译器只会创建一个匿名类型定义,但创建该类型的多个实例.o1=o2
  • 匿名类型的实例不能泄露到方法外部.
  • 方法原型不能接受匿名类型的参数.
  • 方法不能返回匿名类型的引用.

10.1.5 System.Tuple类型

  1. //Tuple没啥好写的,还是写写dynamic吧
  2. dynamic e = new System.Dynamic.ExpandoObject();
  3. e.x = 6; //添加一个Int32 'x'属性,其值为6
  4. e.y = "Jeff"; //添加一个String 'y'属性,其值为"Jeff"
  5. e.z = null; //添加一个Object 'z'属性,其值为null
  6. //查看所有属性及其值:
  7. foreach (var v in (IDictionary<String, Object>)e)
  8. Console.WriteLine("key={0},v={1}", v.Key, v.Value);

10.2 有参属性(c#称为索引器)

  1. public sealed class BitArray
  2. {
  3. //容纳了二进制位的私有字节数组
  4. private byte[] m_byteArray;
  5. private int m_numBits;
  6. //下面的构造器用于分配字节数组,并将所有位设为0
  7. public BitArray(int numBits)
  8. {
  9. //先验证实参
  10. if (numBits <= 0)
  11. throw new ArgumentOutOfRangeException(nameof(numBits));
  12. //保存位的个数
  13. m_numBits = numBits;
  14. //为位数组分配字节
  15. m_byteArray = new byte[(numBits + 7) / 8];
  16. }
  17. //下面是索引器(有参属性)
  18. public bool this[int bitPos]
  19. {
  20. //下面是索引器的get访问器方法
  21. get
  22. {
  23. //先验证实参
  24. if ((bitPos < 0) || (bitPos >= m_numBits))
  25. throw new ArgumentOutOfRangeException(nameof(bitPos));
  26. //返回指定索引处的位的状态
  27. return (m_byteArray[bitPos / 8] & (1 << (bitPos % 8))) != 0;
  28. }
  29. //下面是索引器的set访问器方法
  30. set
  31. {
  32. if ((bitPos < 0) || (bitPos >= m_numBits))
  33. throw new ArgumentOutOfRangeException(nameof(bitPos), bitPos.ToString());
  34. if (value)
  35. {
  36. //将指定索引处的位设为true
  37. m_byteArray[bitPos / 8] = (byte)(m_byteArray[bitPos / 8] | (1 << (bitPos % 8)));
  38. }
  39. else
  40. {
  41. //将指定索引处的位设为false
  42. m_byteArray[bitPos / 8] = (byte)(m_byteArray[bitPos / 8] & ~(1 << (bitPos % 8)));
  43. }
  44. }
  45. }
  46. }

BitArray类的索引器用起来很简单:

  1. //分配含14个位的BitArray数组
  2. BitArray ba = new BitArray(14);
  3. //调用set访问器方法,将编号为偶数的所有位都设为true
  4. for (int x = 0;x < 14; x++){
  5. ba[x]=(x % 2 == 0);
  6. }
  7. //调用get访问器方法显示所有位的状态
  8. for (int x = 0; x < 14; x++){
  9. Console.WriteLine("Bit " + x + " is " +(ba[x] ? "On" : "Off"));
  10. }
  • 可以通过IndexerNameAttribute特性改变编译器使用的索引器名称(默认为Item,并在前面加get_或set_前缀).System.String改变索引器名称为 Chars .
  • c#允许一个类型定义多个索引器,只要索引器的参数集不同.
  • 对于支持多个有参属性的编程语言,必须选中一个有参属性,通过DefaultMemberAttribute特性来标识.这是C#代码唯一能访问的有参属性.

10.3 调用属性访问器方法时的性能

  • 对于简单的get和set访问器方法,JIT编译器会将代码内联(inline,或者说嵌入).

10.4 属性访问器的可访问性

  1. // ⑴
  2. public class SomeType{
  3. private string m_name;
  4. public string Name {
  5. get { return m_name; }
  6. // ⑵
  7. protected set { m_name = value; }
  8. }
  9. }
  • ⑴ 必须为属性本身指定限制最小的可访问性
  • ⑵ 两个访问器只能选择一个来使用限制较大的

返回目录

<NET CLR via c# 第4版>笔记 第10章 属性的更多相关文章

  1. <NET CLR via c# 第4版>笔记 第19章 可空值类型

    System.Nullable<T> 是结构. 19.1 C# 对可空值类型的支持 C# 允许用问号表示法来声明可空值类型,如: Int32? x = 5; Int32? y = null ...

  2. <NET CLR via c# 第4版>笔记 第18章 定制特性

    18.1 使用定制特性 FCL 中的几个常用定制特性. DllImport 特性应用于方法,告诉 CLR 该方法的实现位于指定 DLL 的非托管代码中. Serializable 特性应用于类型,告诉 ...

  3. <NET CLR via c# 第4版>笔记 第17章 委托

    17.1 初识委托 .net 通过委托来提供回调函数机制. 委托确保回调方法是类型安全的. 委托允许顺序调用多个方法. 17.2 用委托回调静态方法 将方法绑定到委托时,C# 和 CLR 都允许引用类 ...

  4. <NET CLR via c# 第4版>笔记 第16章 数组

    //创建一个一维数组 int[] myIntegers; //声明一个数组引用 myIntegers = new int[100]; //创建含有100个int的数组 //创建一个二维数组 doubl ...

  5. <NET CLR via c# 第4版>笔记 第13章 接口

    13.1 类和接口继承 13.2 定义接口 C#用 interface 关键字定义接口.接口中可定义方法,事件,无参属性和有参属性(C#的索引器),但不能定义任何构造器方法,也不能定义任何实例字段. ...

  6. <NET CLR via c# 第4版>笔记 第12章 泛型

    泛型优势: 源代码保护 使用泛型算法的开发人员不需要访问算法的源代码.(使用c++模板的泛型技术,算法的源代码必须提供给使用算法的用户) 类型安全 向List<DateTime>实例添加一 ...

  7. <NET CLR via c# 第4版>笔记 第5章 基元类型、引用类型和值类型

    5.1 编程语言的基元类型 c#不管在什么操作系统上运行,int始终映射到System.Int32; long始终映射到System.Int64 可以通过checked/unchecked操作符/语句 ...

  8. <NET CLR via c# 第4版>笔记 第6章 类型和成员基础

    6.1 类型的各种成员 6.2 类型的可见性 public 全部可见 internal 程序集内可见(如忽略,默认为internal) 可通过设定友元程序集,允许其它程序集访问该程序集中的所有inte ...

  9. <NET CLR via c# 第4版>笔记 第7章 常量和字段

    7.1 常量 常量 是值从不变化的符号.定义常量符号时,它的值必须能够在编译时确定. 只能定义编译器识别的基元类型的常量,如果是非基元类型,需把值设为null. 常量的值直接嵌入代码,所以不能获取常量 ...

随机推荐

  1. qt——类大全

    qt类总结地址 http://www.kuqin.com/qtdocument/ QWidget.QDialog及QMainWindow的区别 QWidget类是所有用户界面对象的基类. 窗口部件是用 ...

  2. 第1章 1.10计算机网络概述--OSI参考模型和TCP_IP协议

    传输层负责将大数据文件分段,变成数据段. 网络层负责为小分段加上IP地址,变成数据包. 数据链路层负责将数包加上MAC地址和校验值,变成数据帧. TCP/IP协议是一群协议.不只是2个协议.

  3. [WorldWind学习]19.WebDownload

    using System; using System.Diagnostics; using System.Globalization; using System.Net; using System.I ...

  4. Mybatis分页查询与动态SQL

    一.Mybatis的分页查询 由于第一二节较为详细讲述了Mybatis的环境搭建,文件配置,SQL编写和Java代码实现,所以接下来的讲述都将只抽取关键代码和mapper文件中的关键sql,详细的流程 ...

  5. Python面试题目之字典排序

    按照字典的内的年龄排序 待排序的字典 d1 = [ {'name':'alice', 'age':38}, {'name':'bob', 'age':18}, {'name':'Carl', 'age ...

  6. 20145322何志威《网络对抗》逆向及Bof基础

    20145322何志威<网络对抗>逆向及Bof基础 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任 ...

  7. 构建一个简单的Linux系统 MenuOs —— start_kernel到init进程(20135304刘世鹏)

    构建一个简单的Linux系统 MenuOs —— start_kernel到init进程 作者:刘世鹏20135304 <Linux内核分析>MOOC课程http://mooc.study ...

  8. ELF文件分析

    (1)文件ELF.c (2)编译: gcc -c ELF_1.c -o ELF_1.o (3)显示文件类型: (4)查看大小: (5)转换为16进制 (6)显示各段信息 (7)分析

  9. RC522 模块驱动程序

    本文主要讲述了基于SPI总线的RC522驱动程序的设计.描述了主控如何与从设备通过SPI总线进行数据的读写. 一 在SPI驱动中,有两个重要的结构:spi_device&spi_driver. ...

  10. Android -- 加载大图片到内存,从gallery获取图片,获取图片exif信息

    1. 加载大图片到内存,从gallery获取图片 android默认的最大堆栈只有16M, 图片像素太高会导致内存不足的异常, 需要将图片等比例缩小到适合手机屏幕分辨率, 再加载. 从gallery ...