本章讨论属性,它允许源代码用简化语法来调用方法。CLR支持两种属性:无参属性 有参属性。在C#中称有参属性索引器

无参属性

面向对象设计和编程的重要原则之一就是数据封装,意味着类型的字段永远不应该公开,否则很容易因为不恰当的使用字段而破坏对象的状态。

下面这种使用方式是不好的:

  1. public sealed class Employee{
  2. public String Name;
  3. public Int32 Age
  4. }
  5. Employee e = new Employee();
  6. e.Name = "Jeffrey Richter";
  7. e.Age = 45;
  8. //下面这种方式很容易就破坏了对象的状态
  9. e.Age = -5;

基于以上原因,强烈建议将所有字段都设为private.要允许用户或类型获取或设置状态信息就公开一个针对该用途的方法。封装了字段访问的方法通常称为访问器方法。

比如下面这样使用属性:

  1. private sealed class Employee {
  2. private String m_Name; // prepended 'm_' to avoid conflict
  3. private Int32 m_Age; // prepended 'm_' to avoid conflict
  4. public String Name {
  5. get { return (m_Name); }
  6. set { m_Name = value; } // 'value' identifies new value
  7. }
  8. public Int32 Age {
  9. get { return (m_Age); }
  10. set {
  11. if (value <= 0) // 'value' identifies new value
  12. throw new ArgumentOutOfRangeException("value", "must be >0");
  13. m_Age = value;
  14. }
  15. }
  16. }
  17. emp.Name = "Jeffrey Richter";
  18. emp.Age = 45; // Updates the age
  19. Console.WriteLine("Employee info: Name = {0}, Age = {1}", emp.Name, emp.Age);
  20. e.Age = -5; // 会抛出`ArgumentOutOfRangeException`异常
  21. Int32 EmployeeAge = e.Age ;

注意:我相信大部分的初学者在开始之初都讲不出字段属性的区别,现在我可以稍微尝试着说下了。字段经常用来封装一些不经常修改的内容,建议将字段设为private,而属性一定要将取值get设值set想象成两个方法,虽然C#简化了这种语法,但编译器在后台仍然会在指定的属性名之前添加set_get_前缀来生成方法名,更适合用来封装那些可能发生变化的内容。可以将属性看成智能字段,可以设置只读属性只写属性

自动实现的属性

  1. public String Name {get;set;}

声明属性而不提供get/set方法的实现,C#会自动为你声明一个私有字段。实现get/set方法。

合理定义属性

  • 属性可以只读或只写,字段访问总是可读或可写的(readonly字段在构造器中可写)。如果定义属性,最好同时位它提供getset访问方法。
  • 属性方法可抛出异常,字段不会
  • 属性不能作为outref参数传递给方法
  • 属性可能花较长时间完成,字段访问总是立即完成
  • 连续多次访问,属性方法可能每次返回不同的值,而字段每次都是相同的值

对象和集合初始化器

对象初始化语法:

  1. Employee e = new Employee(){ Name = "Jeff" , Age = 45 };

如果想调用的本来就是一个无参构造器,C#还允许省略括号

下面演示集合初始化器,下面构造一个ClassRoom对象,并初始化Students集合

  1. Classroom classroom = new Classroom{
  2. Student = { "Jeff" , "Kristin" , "Aidan"}
  3. };

使用起来还是非常方便的,编译器在后台默认调用集合的Add方法,把对象添加到集合中。

匿名类型

利用C#的匿名类型功能,可以很简洁的语法来自动声明不可变的元组类型。

  1. var o1 = new { Name = "Jeff", Year = 1964 };
  2. // Display the properties on the console:
  3. Console.WriteLine("Name={0}, Year={1}", o1.Name, o1.Year);

匿名类型经常与LINQ联合使用

有参属性

在C#中有参属性被称为索引器。C#是用数组风格的语法来公开有参属性,换句话说索引器可以看成是C#对[]操作符的重载

下面演示一个BitArray类,它允许哦那个数组风格的语法来索引一组二进制位

  1. internal sealed class BitArray {
  2. //容纳了一个二进制位的私有字节数组
  3. // Private array of bytes that hold the bits
  4. private Byte[] m_byteArray;
  5. private Int32 m_numBits;
  6. // Constructor that allocates the byte array and sets all bits to 0
  7. //分配字节数组,并将所有为初始为0
  8. public BitArray(Int32 numBits) {
  9. // Validate arguments first.
  10. if (numBits <= 0)
  11. throw new ArgumentOutOfRangeException("numBits must be > 0");
  12. // Save the number of bits.
  13. m_numBits = numBits;
  14. // Allocate the bytes for the bit array.
  15. m_byteArray = new Byte[(m_numBits + 7) / 8];
  16. }
  17. // This is the indexer.
  18. // 这是索引器
  19. public Boolean this[Int32 bitPos] {
  20. // 这是索引器的get方法
  21. get {
  22. // Validate arguments first
  23. if ((bitPos < 0) || (bitPos >= m_numBits))
  24. throw new ArgumentOutOfRangeException("bitPos", "bitPos must be between 0 and " + m_numBits);
  25. // Return the state of the indexed bit.
  26. return ((m_byteArray[bitPos / 8] & (1 << (bitPos % 8))) != 0);
  27. }
  28. // 索引器的set访问器方法
  29. set {
  30. if ((bitPos < 0) || (bitPos >= m_numBits))
  31. throw new ArgumentOutOfRangeException("bitPos", "bitPos must be between 0 and " + m_numBits);
  32. if (value) {
  33. // Turn the indexed bit on.
  34. m_byteArray[bitPos / 8] = (Byte)
  35. (m_byteArray[bitPos / 8] | (1 << (bitPos % 8)));
  36. } else {
  37. // Turn the indexed bit off.
  38. m_byteArray[bitPos / 8] = (Byte)
  39. (m_byteArray[bitPos / 8] & ~(1 << (bitPos % 8)));
  40. }
  41. }
  42. }
  43. }
  44. private static void BitArrayTest() {
  45. // Allocate a BitArray that can hold 14 bits.
  46. // 构造一个数组
  47. BitArray ba = new BitArray(14);
  48. // Turn all the even-numbered bits on by calling the set accessor.
  49. for (Int32 x = 0; x < 14; x++) {
  50. //这里实际是调用的set方法,将偶数为设为true
  51. ba[x] = (x % 2 == 0);
  52. }
  53. // Show the state of all the bits by calling the get accessor.
  54. for (Int32 x = 0; x < 14; x++) {
  55. // 这里调用了get方法,显示状态。
  56. Console.WriteLine("Bit " + x + " is " + (ba[x] ? "On" : "Off"));
  57. }
  58. }

C#使用this[...]作为表达索引器的语法,如上面的

  1. public Boolean this[Int32 bitpos]

代表set时,传入一个index的索引,get时返回一个Boolean类型


总结

今天的内容还是比较有趣的, 搞懂了一直以来困惑的字段属性的区别。复习了对象初始化器、集合初始化器、匿名类型等等,最后学习了下有参属性即索引器。以前在做题的时候遇到过,现在也清楚多了。接下来到了事件了哈哈,做个小栗子一起学习下吧。

C#--属性详解的更多相关文章

  1. android:exported 属性详解

    属性详解 标签: android 2015-06-11 17:47 27940人阅读 评论(7) 收藏 举报 分类: Android(95) 项目点滴(25) 昨天在用360扫描应用漏洞时,扫描结果, ...

  2. OutputCache属性详解(一)一Duration、VaryByParam

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  3. OutputCache属性详解(二)一 Location

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  4. OutputCache属性详解(三)— VaryByHeader,VaryByCustom

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  5. OutputCache属性详解(四)— SqlDependency

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  6. WPF依赖属性详解

    WPF依赖属性详解 WPF 依赖属性 英文译为 Dependency Properties,是WPF引入的一种新类型的属性,在WPF中有着极为广泛的应用,在WPF中对于WPF Dependency P ...

  7. HTML video 视频标签全属性详解

    HTML 5 video 视频标签全属性详解   现在如果要在页面中使用video标签,需要考虑三种情况,支持Ogg Theora或者VP8(如果这玩意儿没出事的话)的(Opera.Mozilla.C ...

  8. Android组件---四大布局的属性详解

    [声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4372222.html Android常见布局有下面几种: LinearL ...

  9. dede的pagelist标签的listsize数字属性详解(借鉴)

    dede的pagelist标签的listsize数字属性详解.见远seo经常用织梦搭建各种网站,有次发现列表页面的分页显示超过div的界限,也就是溢出了或者说是撑破了.后来经过研究发现是pagelis ...

  10. 轻松学习Linux之Shell文件和目录属性详解

    轻松学习Linux之Shell文件和目录属性详解 轻松学习Linux之理解Sitcky 轻松学习Linux之理解umask 轻松学习Linux之理解SUID&SGUID 本系列多媒体教程已完成 ...

随机推荐

  1. C语言实现控制台中光标随意移动

    开始准备学习下C,新手哦~~ 今天弄了个控制台程序,光标可以随意在DOS下移动~~ 先放一张效果图,不过很丑,大家能不能看懂,哈哈,就是 I Love You. 代码注释都有,其实好多东西我都是从其他 ...

  2. SSE指令集优化学习:双线性插值

    对SSE的学习总算迈出了第一步,用2天时间对双线性插值的代码进行了优化,现将实现的过程梳理以下,算是对这段学习的一个总结. 1. 什么是SSE 说到SSE,首先要弄清楚的一个概念是SIMD(单指令多数 ...

  3. “SqlDateTime 溢出。必须介于 1/1/1753 12:00:00 AM 和 12/31/9999 11:59:59 PM 之间。”

    原因: .NET中  DateTime最小值为: 0001-1-1 0:00:00 数据库中DateTime最小值为: 1753-1-1 0:00:00, 很明显:.NET中的最小值超出了数据库时间类 ...

  4. 基于python的七种经典排序算法

    参考书目:<大话数据结构> 一.排序的基本概念和分类 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法. ...

  5. Java进击C#——语法之面向对象

    本章简言 上一章笔者讲到关于ADO.NET相关的知识,知道了如何去访问数据库.本章将来讲关于面向对象的思想.不管在JAVA还是在C#面向对象思想的重要性都是占了一个很大的成份.往往他就像呼吸一样子,更 ...

  6. Net设计模式实例之桥接模式( Bridge Pattern)

    一.桥接模式简介(Brief Introduction) 桥接模式(Bridge Pattern),将抽象部分与它的实现部分分离,使的抽象和实现都可以独立地变化. Decouple an abstra ...

  7. 在 .NET 中远程请求 https 内容时,发生错误:根据验证过程,远程证书无效。

    当访问 https 内容的时候,有时候经常会看到证书错误(不在操作系统的证书信任链中?)的提示,在浏览器中我们可以忽略错误的证书,继续访问网页内容. 但是在 .NET 程序中,需要由代码来判断是否忽略 ...

  8. asp.net的快捷实用分页类

    KeleyiPager分页类,可以于对列表页进行分页浏览,代码是从HoverTreeCMS项目中COPY的,感觉很不错,使用简单方便,但是功能强大. 在线体验效果:http://cms.hovertr ...

  9. 异步与并行~ReaderWriterLockSlim实现的共享锁和互斥锁

    返回目录 在System.Threading.Tasks命名空间下,使用ReaderWriterLockSlim对象来实现多线程并发时的锁管理,它比lock来说,性能更好,也并合理,我们都知道lock ...

  10. 动态加载js和css

    开发过程中经常需要动态加载js和css,今天特意总结了一下常用的方法. 1.动态加载js 方法一:动态加载js文件 // 动态加载js脚本文件 function loadScript(url) { v ...