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章 类型和成员基础的更多相关文章

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

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

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

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

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

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

  4. 《CLR via C#》读书笔记(6)类型和成员基础

    6.1 类型的各种成员 在一个类型中,可以定义0个或者多个以下种类的成员: 常量 常量是在编译时设置其值并且永远不能更改其值的字段.使用常量可以为特殊值提供有意义的名称以代替数字文本,以使代码变得更容 ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. mysql 数据操作 单表查询 group by 介绍

    group by 是在where 之后运行 在写单表查询语法的时候 应该把group by 写在 where 之后 执行顺序 1.先找到表 from 库.表名 2.按照where 约束条件 过滤你想要 ...

  2. LVM的一些问题汇总 tune2fs命令

    LVM的一些问题汇总  tune2fs命令 --http://www.aminglinux.com/bbs/forum.php?mod=viewthread&tid=7664&page ...

  3. spring Security 得到认证用户名的方法

    @Service("userService")public class UserServiceImpl implements UserService { @Overridepubl ...

  4. python开发之路目录

    Python 目录 基础 python入门 python数据类型.字符编码.文件处理 python函数基础 python函数进阶 python装饰器函数 python装饰器函数 python递归函数 ...

  5. poj3608 Bridge Across Islands

    地址:http://poj.org/problem?id=3608 题目: Bridge Across Islands Time Limit: 1000MS   Memory Limit: 65536 ...

  6. hdu5021 树状数组+二分

    这 题 说 的 是 给 了 一 个 K—NN    每次查询离loc 最近的k个数 然后将这k个数的权值加起来除以k 赋值给 loc 这个位置上的 权值  我说说 我的做法 假如 查询的是loc 这个 ...

  7. Linux命令: grep命令

    基本用法                                                                                                 ...

  8. Linux查看网卡UUID另一方法

    转自:http://liaoronghui.com/linux-view-network-adapter-uuid-other-law.html 有时我们不小心将/etc/sysconfig/netw ...

  9. IntelliJ idea的初次使用

    1. 首次使用Idea工具,需要安装.我安装的版本是14.0.2.安装包下载地址 http://pan.baidu.com/s/1gfFkrzt 2. 安装SVN. 3.配置JDK. 4.配置mave ...

  10. 【运维技术】Jenkins配置使用教程

    Jenkins配置使用教程 单机jenkins启动 软件安装和启动,必须含有java环境 # 安装jdk,参考其他教程,创建文件目录 mkdir -p /app/jenkins cd /app/jen ...