<NET CLR via c# 第4版>笔记 第6章 类型和成员基础
6.1 类型的各种成员
6.2 类型的可见性
public 全部可见
internal 程序集内可见(如忽略,默认为internal)
可通过设定友元程序集,允许其它程序集访问该程序集中的所有internal 类型.例如想允许强命名"Microsoft"程序集访问本程序集内的internal类型:
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Microsoft,PublicKey=b77a5c56...1934e089")]
6.3 成员的可访问性
private 成员只能由定义类型或任何嵌套类型中的方法访问
protected 成员只能由定义类型、任何嵌套类型或者不管在什么程序集中的派生类型中的方法访问
internal 成员只能由定义程序集中的方法访问
protected internal 成员可由任何嵌套类型、任何派生类型(不管在什么程序集)或者定义程序集中的任何方法访问
public 成员可由任何程序集的任何方法访问
C#中,如果没有显式声明成员的可访问性,编译器通常(但并不总是)默认选择private(限制最大的那个)。
派生类重写基类型定义的成员时,C#编译器要求原始成员和重写成员具有相同的可访问性。
6.4 静态类
静态类必须直接从基类
System.Object派生。静态类不能实现任何接口。
静态类只能定义静态成员(字段、方法、属性和事件)
静态类不能作为字段、方法参数或局部变量使用。
6.5 分部类、结构和接口
- partial关键字告诉C#编译器:类、结果或接口的定义源代码可能要分散到一个或多个源代码文件中(C#编译器实现,和CLR无关)。
6.6 组件、多态和版本控制
| C#关键字 | 类型 | 方法/属性/事件 | |
|---|---|---|---|
| abstract | 表示不能构造该类型的实例 | 表示为了构造派生类型的实例,派生类型必须重写并实现这个成员 | |
| virtual | (不允许) | 表示这个成员可由派生类型重写 | |
| override | (不允许) | 表示派生类型正在重写基类型的成员 | |
| sealed | 表示该类型不能用作基类型 | 表示这个成员不能被派生类型重写,只能将该关键字应用于重写虚方法的方法 | |
| new | 应用于嵌套类型、方法、属性、事件、常量或字段时,表示该成员与基类中相似的成员无任何关系 | ||
6.6.1 CLR如何调用虚方法、属性和事件
call 该IL指令可调用静态方法、实例方法和虚方法。
callvirt 该IL指令可调用实例方法和虚方法,不能调用静态方法。
callvirt以多态方式调用虚实例方法,调用时,JIT编译器会验证变量的值是否为NULL,执行速度比call指令稍慢。
c#团队认为,JIT编译器应生成代码来验证发出调用的对象不为null.所以,C#用 callvirt 指令调用所有实例方法。
如果使用C#外的其它语言,定义了非虚方法后,将来永远都不要把它更改为虚方法。这是因为某些编译器会用 call 而不是 callvirt 调用非虚方法。如果方法从非虚变成虚,而引用代码没有重新编译,会以非虚方式调用虚方法,造成应用程序无法预料。
设计类型时应尽量减少虚方法数量,因为:
- 调用虚方法的速度比调用非虚方法慢;
- JIT编译器不能内嵌(inline)虚方法,这进一步影响性能;
- 虚方法使组件版本控制变得更脆弱;
- 定义基类型时,经常要提供一组重载的简便方法(convenience method)。如果希望这些方法是多态的,最好的办法就是使最复杂的方法成为虚方法,使所有重载的简便方法成为非虚方法。
6.6.2 合理使用类型的可见性和成员的可访问性
尽量使用关键字 sealed 将类显式标记为密封,性能优于非密封类。
尽量将类指定为 internal (C#编译器默认使用的就是 internal)
类的内部,将数据字段定义为 private (C#默认),除了public,尽量连protected和internal也不用。
类的内部,避免使用protected或internal,因为这会使类型面临更大的安全风险。virtual永远最后才考虑。
6.6.3 对类型进行版本控制时的虚方法的处理
<NET CLR via c# 第4版>笔记 第6章 类型和成员基础的更多相关文章
- <NET CLR via c# 第4版>笔记 第16章 数组
//创建一个一维数组 int[] myIntegers; //声明一个数组引用 myIntegers = new int[100]; //创建含有100个int的数组 //创建一个二维数组 doubl ...
- <NET CLR via c# 第4版>笔记 第13章 接口
13.1 类和接口继承 13.2 定义接口 C#用 interface 关键字定义接口.接口中可定义方法,事件,无参属性和有参属性(C#的索引器),但不能定义任何构造器方法,也不能定义任何实例字段. ...
- <NET CLR via c# 第4版>笔记 第7章 常量和字段
7.1 常量 常量 是值从不变化的符号.定义常量符号时,它的值必须能够在编译时确定. 只能定义编译器识别的基元类型的常量,如果是非基元类型,需把值设为null. 常量的值直接嵌入代码,所以不能获取常量 ...
- 《CLR via C#》读书笔记(6)类型和成员基础
6.1 类型的各种成员 在一个类型中,可以定义0个或者多个以下种类的成员: 常量 常量是在编译时设置其值并且永远不能更改其值的字段.使用常量可以为特殊值提供有意义的名称以代替数字文本,以使代码变得更容 ...
- <NET CLR via c# 第4版>笔记 第19章 可空值类型
System.Nullable<T> 是结构. 19.1 C# 对可空值类型的支持 C# 允许用问号表示法来声明可空值类型,如: Int32? x = 5; Int32? y = null ...
- <NET CLR via c# 第4版>笔记 第18章 定制特性
18.1 使用定制特性 FCL 中的几个常用定制特性. DllImport 特性应用于方法,告诉 CLR 该方法的实现位于指定 DLL 的非托管代码中. Serializable 特性应用于类型,告诉 ...
- <NET CLR via c# 第4版>笔记 第17章 委托
17.1 初识委托 .net 通过委托来提供回调函数机制. 委托确保回调方法是类型安全的. 委托允许顺序调用多个方法. 17.2 用委托回调静态方法 将方法绑定到委托时,C# 和 CLR 都允许引用类 ...
- <NET CLR via c# 第4版>笔记 第12章 泛型
泛型优势: 源代码保护 使用泛型算法的开发人员不需要访问算法的源代码.(使用c++模板的泛型技术,算法的源代码必须提供给使用算法的用户) 类型安全 向List<DateTime>实例添加一 ...
- <NET CLR via c# 第4版>笔记 第5章 基元类型、引用类型和值类型
5.1 编程语言的基元类型 c#不管在什么操作系统上运行,int始终映射到System.Int32; long始终映射到System.Int64 可以通过checked/unchecked操作符/语句 ...
随机推荐
- cocos代码研究(23)Widget子类ScrollView学习笔记
基础理论 一个能够被用户触摸滚动的一个层次型布局容器视图,允许其尺寸大于屏幕显示的物理尺寸,其内部维护有一个布局用于水平的或垂直的存放子节点.继承自 Layout,被 ListView 继承. 代码实 ...
- 72. Edit Distance(编辑距离 动态规划)
Given two words word1 and word2, find the minimum number of operations required to convert word1 to ...
- uva1292 树形dp
这题说的是给了一个n个节点的一棵树,然后 你 从 这 棵 树 的 n 个 节点中 选择 尽量少的 点使得 每条边都至少有一个 士兵看守 dp[0][i]+=dp[1][j] dp[1][i]+=min ...
- 20145326 《Java程序设计》第3周学习总结
20145326 <Java程序设计>第3周学习总结 教材学习内容总结 > 从了解java平台概论,JDK到IDE的介绍,基础语法的运用到现在的类与对象,封装.前三章的知识其实都不是 ...
- [问题解决]不使用PWM调速系统,彻底解决一个L298N带动两个电机却转速不同的问题
问题描述:由单片机的VCC引脚供电,使用L298N控制两个电机,发现左右两个轮子的转速老是不一样,更多的情况是左轮转速高(左轮电机接OUT1和OUT2),右轮转速低(右轮电机接OUT3和OUT4)甚至 ...
- luogu P1141 01迷宫
https://www.luogu.org/problem/show?pid=1141 还不太会用 BFS 然后就跟着感觉走了一波 经历了很多错误 刚开始的读入 然后BFS的过程 最后T三个点 看到别 ...
- 51Nod 1686 第K大区间(离散化+尺取法)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1686 题意: 思路: 第K大值,所以可以考虑二分法,然后用尺取法去扫描, ...
- QT 正则表达式无效
背景:写了一个判断IP地址合法的正则表达式,并让它应用在输入框中 代码如下 QRegExp rx_ip("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}( ...
- Sublime编辑器上的Linux Vim插件常用快捷键
Sublime编辑器上的 Vim 插件常用快捷键 vim 的设置: 在Reference-> User Settings(首选项--> 设置用户) 选项,点击进入配置文件编辑状态,默认的用 ...
- perl模块终极解决方案--转载
不管别人怎么说,反正我是非常喜欢perl语言的! 也会继续学习,以前写过不少perl模块的博客,发现有点乱,正好最近看到了关于local::lib这个模块. 居然是用来解决没有root权限的用户安装, ...