CLR via C#学习笔记-第十章-无参属性
10.1 无参属性
面向对象设计和编程的重要原则之一就是数据封装,意味着类型的字段永远不应该公开,否则很容易因为不恰当使用字段而破坏对象的状态。
建议将所有字段都设为private。要允许用户或类型设置、获取状态信息,就公开一个针对该用途的方法。
封装了字段访问的方法通常称为访问器accessor方法。
CLR提供了属性property的机制,减少了访问器方法的缺点
private String m_Name; public String Name {get{return (m_name);}set{m_name=value;} }
可将属性想象成智能字段,即背后有额外逻辑的字段。
CLR支持静态、实例、抽象和虚属性。另外,属性可以认有可访问性修饰符来标记。
属性的特点
每个属性都有名称和类型(不能是void)。
属性不能重载,即不能定义名称相同类型不同的两个属性。
定义属性时通常同时指定get和set两个方法。但可以省略其中之一实现只读、只写。
利用属性的set、get操纵类型定义的私有字段。
私有字段通常称为支持字段 backing field。
但get、set方法并非一定要访问支持字段。
属性本质是方法
以前面的Name属性为例,由于有get、set访问器方法,
所以编译器在类型中生成两个方法定义,就像原始代码是这样写的一样
private String m_Name; public String GetName(){return m_name} public void set_Name(String value){m_Name=value;}
编译器在你指定的属性名之前自动附加get_或者set_前缀来生成方法名,C#内建了对属性的支持。
当C#编译器发现代码试图获取设置属性时,实际会生成对上述某个方法的的调用。
CLR只认访问器方法
除了生成访问器方法,针对源代码中定义的每一个属性,编译器还会在托管程序集中的元数据中生成一个属性定义项。
在这个记录项中,包含了一些标志flags以及属性的类型。
另外还引用了get、set访问器方法。这些信息的唯一作用是在属性这种抽象概念与他的访问器方法之间建立一个联系。
编译器和其它工具可以利用这种元数据,使用System.Reflection.PropertyInfo类来获得。
CLR不使用这种元数据信息,运行时只需要访问器方法。
10.1.1 自动实现的属性
如果只是为了封装一个支持字段而创建属性。C#提供了一种更简洁的语法,称为自动实现的属性 Automatically Implemented Property,AIP。
public String Name{get;set;}
升麻属下而不提供get/set方法的实现,C#自动为你声明一个私有字段。编译器会自动实现get_Name,setName方法,分别返回和设置字段中的值。
AIP的特点
使用AIP,意味着你已经创建了一个属性,访问该属性的任何代码实际都会调用get,set方法。
如果以后要自己实现get、set方法,而不是接受编译器的默认实现,访问属性的任何代码都不必重新编译。
然而,如果将Name声明为字段,以后又想把他改为属性,那么访问字段的所有代码都必须重新编译才能访问属性方法。
AIP的缺点
1.作者不喜欢AIP,避免使用AIP。因为字段声明语法可能包含初始化,
2.运行时序列化引擎将字段名持久存储到序列化的流中。AIP的支持字段名由编译器决定,每次重新编译都可能更改这个名称。因此,任何类型只要含有一个AIP,就没办法对该类型进行反序列化。
3.调试时不能在AIp的get、set上添加断点。
如果使用AIP,属性必然是可读和可写的。AIP作用域整个属性,要么都用要么都不用。
10.1.2 合理定义属性
作者不喜欢属性,看起来像字段,本质是方法,使人误解,程序员在看到貌似访问字段的代码时,会做出一些对属性来说不成立的假定,具体如下。
1.属性可以只读或只写,而字段访问总是可读和可写的,除了1readonly仅在构造器中可写。如果定义属性,最好同时为他提供get、set。
2.属性方法可能抛出异常,字段不会。
3.属性不能作为out、ref参数传给方法,字段可以。
4.属性方法可能花费较长时间执行,字段访问总是立即完成。许多人使用属性是为了线程同步,这就可能造成线程永远终止。所以,要线程同步就不要使用舒徐而要使用方法。
5.连续多次调用,属性方法每次都可能返回不同的值,字段则每次都返回相同的值。
6.属性方法可能需要额外内存,或者返回的引用并非指向对象状态一部分,造成对返回对象的修改做用不到原始对象身上。而查询字段返回的引用总是只想原始对象状态的一部分。使用会返回一个拷贝属性很容易引起混淆。
10.1.3 对象和集合初始化器
经常要构造一个对象并设置对象的一些公共属性或字段,C#提供了一种特殊的对象初始化语法来简化这种常见的编程模式。
Employee e=new Employee(){Name="Jeff",Age=45};
这一句代码构造了一个Employee对象,调用它的无参构造器,将其公共属性Name设为"Jeff",Age属性设为45。实际上这等价于以下几行代码。
Employee e=new Employee(); e.Name="Jeff"; e.Age=45;
对象初始化器的好处
对象初始化器语法真正的好处在于,允许在表达式的上下文中编码,允许组合多个函数。
String s=new Employee(){Name="Jeff",Age=45}.ToString().ToUpper();
这个语句首先构造一个Employee对象,调用它的构造器,再初始化两个公共属性,然后在结果表达式上,先调用ToString,再调用ToUpper。
补充一下,如果想调用的本来就是一个无参构造器,C#允许省略起始大括号之前的圆括号,下面这行代码与上一行生成相同的IL。
String s=new Employee{Name="Jeff",Age=45}.ToString().ToUpper();
如果属性的类型实现了IEnumerable或IEnumerable<T>接口,属性就被认为是集合,而集合的初始化是一种相加操作而非替换操作。比如像下面初始化Classroom对象的Student集合。
Classroom classroom=new Classroom{Students={"Jeff","Tom","Kim"}};
假定List<String>类型提供了名为Add的方法,上述代码会被编译器转换成这样。
Classroom classroom=new Classroom(); classroom.Students.Add("Jeff"); classroom.Students.Add("Tom"); classroom.Students.Add("Kim");
如果属性的类型实现了IEnumerable或IEnumerable<T>,但未提供Add方法,编译器就不允许使用集合初始化语法向集合中添加数据项。
使用集合初始化器语法初始化Dictionary
有的集合的Add方法要获取多个实参,比如Dictionary的Add
public void Add(TKey key,TValue value);
通过在集合初始化器中嵌套大括号的方式可向Add方法传递多个实参,如下所示。
var table=new Dictionary<String,Int32>{{"Jeffrey",1},{"Kristin",2}}
它等价于以下代码
var table=new Dictionary<String,Int32>(); table.Add("Jeffrey",1); table.Add("Kristin",1);
10.1.4 匿名类型
利用C#的匿名类型功能,可以用很简洁的语法来自动声明不可变的元组类型。
元组类型是含有一组属性的类型,这些属性通常以某种方式互相关联。
以下代码定义了一个含有两个属性的类,构造了该类型的实例。
var o1=new {Name="Jeff",Year=1964};
这行代码创建了匿名类型,没在new关键字后指定类型名称,编译器会自动创建类型名称,而且不会告诉你这个名称是什么,这正是匿名的含义。
这行代码使用对象初始化器语法来声明属性同时初始化。
编译器如何处理匿名类型
编译器会推断每个表达式的类型,创建类型的私有字段,为每个字段创建公共只读属性,并创建一个构造器来接受所有这些表达式。在构造器的代码在,会用传给他的表达式的求值结果来初始化私有只读字段。
除此之外,编译器还会重写Object的Equals,GetHashCode和ToString方法,并生成所有这些方法中的代码。
因此匿名类型的实例能放到哈希表集合中。
属性是只读的,目的是防止对象的哈希码发生改变。如果对象在哈希表中作为键来使用,更改他的哈希码会再也找不到她。
多个相同结构的匿名类型
如果你定义多个匿名类型,而这些类型具有相同的结构,那么编译器只会创建一个匿名类型定义,但创建多个实例。
两个匿名类型实例可以检查两个对象是否包含相等的值,将一个对象的引用赋给正在指向另一个对象的变量。
由于这种类型的同一性,可以创建一个隐式类型的数组,在其中包含一组匿名类型的对象
匿名类型的其他注意事项
匿名类型经常与LINQ配合使用。
匿名类型的实例不能泄露到方法外部,方法原型不接受匿名类型的参数。防范也不能返回对匿名类型的引用。
转载于:https://www.cnblogs.com/errornull/p/9833910.html
CLR via C#学习笔记-第十章-无参属性相关推荐
- 《Go语言圣经》学习笔记 第十章 包和工具
<Go语言圣经>学习笔记 第十章 包和工具 目录 包简介 导入路径 包声明 导入声明 包的匿名导入 包和命名 工具 注:学习<Go语言圣经>笔记,PDF点击下载,建议看书. G ...
- CLR Via C# 学习笔记(5) 静态构造函数的性能
CLR Via C#>这本书以前就粗略看过两遍,但一直都没能深入理解,而且很多内容也忘记了,现在准备重新看一遍,并将看过的部分写出来,因为写的过程也是一个加深理解的过程.本系列算是学习的一个记录 ...
- Pytorch学习笔记-第十章
Pytorch学习笔记-第十章图像描述 model data_preprocess data feature_extract main 记录一下个人学习和使用Pytorch中的一些问题.强烈推荐 &l ...
- C++ Primer 学习笔记 第十章 泛型算法
C++ Primer 学习笔记 第十章 泛型算法 336 find函数 #include <iostream> #include <vector> #include <s ...
- CLR via C#学习笔记-第十三章-定义接口、继承接口
13.1 类和接口继承 接口是为了实现多继承 所有的类都继承了System.Object,及其四个公共实例方法:ToString.Equals.GetHashCode.GetType. CLR允许定义 ...
- matlab 轴gui,MatlabüGUI学习笔记(4)——公共对象属性的轴,MatlabGUI,四,常用,之,Axes...
Matlab_GUI学习笔记(四)--常用对象的属性之Axes 1. Axes Axes意为"轴",是axis的复数.使用get函数查看Axes对象的属性,有一些属性与Figure ...
- LabView学习笔记(八):属性节点
Labview学习笔记: LabView学习笔记(一):基础介绍 LabView学习笔记(二):滤波器实验 LabView学习笔记(三):基本控件 LabView学习笔记(四):动态数据类型 LabV ...
- 【Vue学习笔记_03】v-bind动态绑定属性
[Vue学习笔记_03]v-bind动态绑定属性 v-bind基本使用 v-bind动态绑定class 对象语法(很常用) 数组语法 v-bind动态绑定style 对象语法 数组语法 配套可执行代码 ...
- 疯狂python讲义学习笔记——中十章完结
#第十一章 thinker import tkinter as tk print(help(tk.Button.__init__))#以按扭为例查看有什么属性 class myApplication( ...
- locust工具学习笔记(三)-Tasks属性、tag修饰符、TaskSet类
locust工具学习笔记(三) 虚拟用户数分配和权重的关系 1.一个场景文件中如果定义多个用户类,用来对不同用户行为进行压测时,可以用weight属性来控制用户行为执行权重 2.当用户权重不足1人时, ...
最新文章
- MySQL存储过程和触发器的实现--数据库学习笔记
- WSAAsyncSelect模型
- Core Linux折腾(二)
- 推荐一个在线查看.cer文件的网站
- SAP License:WBS结果分析
- android imageview scaletype 按钮状态,Android ImageView 之 ScaleType 详解
- 二:Unity 3D 脚本介绍
- TDengine在智慧城市大数据管理系统中的应用实践
- excel--text(双坐标图表)
- 叩丁狼java培训:LinkedList的原理介绍
- Python 自定义程序打包 --- face_recognition 篇
- 工业相机——感光元件尺寸介绍
- Motion-based Detection and Tracking in 3D LiDAR Scans
- 我的Android说
- Python简单网页抽奖
- BN层的解释说明(包含梯度消失和梯度爆炸的原理及解决方法)
- 基于vivado的IP设计与管理
- 【跨境电商】疫情下做好海外跨境电商的几个技巧你知道吗?
- python恶搞表情包-关于python表情包
- supermap 缓冲区分析
热门文章
- 16.Mongodb之预写日志(Journaling)
- php钩子配置,thinkphp 行为扩展 钩子与插件的实现
- 虚拟机中利用qemu调试跟踪linux内核
- 查看linux版本是 centos还是ubuntu
- exists sql用法_《SQL进阶教程》笔记(3)
- c语言+游戏破解,c语言获得键盘的按键
- cloudare mysql 密码修改_CentOS7.3 LAMP环境搭建私有云NextCloud过程记录
- 7.3 环境(Condition)
- Spring之不同步的Bean
- 【渝粤教育】21秋期末考试社会学概论10082k1