1、接口对一组方法签名进行了统一命名。接口还能定义事件、无参属性和有参属性(C#的索引器)。

2、c#禁止接口定义任何一种静态成员。

3、C#编译器要求将实现接口的方法标记为public。CLR要求将接口的方法标记为virtual。不将方法显示标记为virtual,编译器会将它们标记为virtual和sealed;这会阻止派生类重写接口方法。将方法显式标记为virtual,编译器就会将方法标记为virtual,使派生类能重写它。派生类不能重写sealed的接口方法。但派生类可重新继承同一个接口,变为接口方法提供自己的实现:

 //这个类派生自Object,它实现了IDisposable
internal class Derived:Base,IDisposable{
//这个方法不能重写Base的Dispose,
//'new'表明该方法重新实现了IDisposable的Dispose方法
new public void Dispose(){
Console.WriteLine("Derived`s Dispose");
//注意,下面这行代码展示了如何调用基类的实现(如果需要的话)
//base.Dispose();
}
}

4、隐式和显示接口方法实现

类型加载到CLR中时,会为该类型创建并初始化一个方法表。在这个方法表中,类型引入的每个新方法都有对应的记录项;另外,还为该类型继承的所有虚方法添加了记录项。继承的虚方法既有继承层次结构中的各个基类型定义的,也有接口类型定义的。

internal sealed class SimpleType:IDisplsable{
public void Dispose(){
Console.WriteLine("Dispose");
}
}

类型的方法表将包含以下方法的记录项。

  • Object(隐式继承的基类)定义的所有虚实例方法。
  • IDisposable(继承的接口)定义的所有接口方法。本例只有一个方法,即Dispose,因为IDisposable接口只定义了这个方法。
  • SimpleType引入的新方法Dispose。

为了简化编程,C#编译器假定SimpleType引入的Dispose方法是对IDisposable的Dispose方法的实现。之所以这样假定,是由于Dispose方法的可访问性public,而接口方法的签名和新引入的方法完全一致。也就是说,两个方法具有相同的参数和返回类型。如果新的Dispose方法被标记为virtual,C#编译器仍然认为方法匹配接口方法。C#编译器将新方法和接口方法匹配起来之后,会生成元数据,指明SimpleType类型的方法表中的两个记录项应引用同一个实现。

现在重新SimpleType,以便于看出区别:

internal sealed class SimpleType:IDisposable{
public void Dispose(){ Console.WriteLine("public Dispose"); }
void IDisposable.Dispose(){ Console.WriteLine("IDisposable Dispose"); }
}

在C#中,将定义方法的那个接口的名称方法名前缀(例如IDisposable.Dispose),就会创建显示接口方法实现(EIMI)。注意,C#中不允许在定义显示接口方法时指定可访问性(比如public或private)。

5、泛型和接口约束

泛型类型参数约束的好处。

第一个好处在于,可将泛型类型参数约束为多个接口。这样一来,传递的参数的类型必须实现全部接口约束。

//M的类型参数T被约束为只支持同时实现了
//IComparable和IConvertitle接口的类型
private static Int32 M<T>(T t)where T:IComparable,IConvertible{
...
}

接口约束的第二个好处是传递值类型的实例时减少装箱。

C#编译器为接口约束生成特殊IL指令,导致直接在值类型上调用接口方法而不是装箱。不用接口约束便没有其他办法让C#编译器生成这些IL指令,如此一来,在值类型上调用接口方法总是发生装箱。一个例外是如果值类型实现了一个接口方法,在值类型的实例上调用这个方法不会造成值类型的实例装箱。

6、设计:基类还是接口

  • IS-A对比CAN-DO关系

   类型只能继承一个实现。如果派生类型和基类型建立不起IS-A关系,就不用基类而用接口。接口意味着CAN-DO关系。如果多种对象类型都“能”做某事,就为它们创建接口。例如,一个类型能将自己的实例转换为另一个类型(IConvertible),一个类型能序列化自己的实例(ISerializable)。注意,值类型必须从System.ValueType派生,所以不能从一个任意的基类派生。这时必须使用CAN-DO关系并定义接口。

  • 易用性
    基类派生比接口容易得多。
  • 一致性实现

  

  • 版本控制

CLR via c#读书笔记九:接口的更多相关文章

  1. CLR via c#读书笔记九:字符、字符串和文本处理

    1.在.NET Framework中,字符总是表示成16位unicode代码值(关于unicode.utf8等可以到http://www.ruanyifeng.com/blog/2007/10/asc ...

  2. [Clr via C#读书笔记]Cp13接口

    Cp13接口 类和接口继承 接口只提供签名,不提供实现:等效于契约:凡事能使用具名接口的地方都能够使用实现了的接口. 定义接口 定义很简单,FCL也提供了大量的现成接口供使用: 继承接口 类不能多继承 ...

  3. CLR via C# 读书笔记-21.托管堆和垃圾回收

    前言 近段时间工作需要用到了这块知识,遂加急补了一下基础,CLR中这一章节反复看了好多遍,得知一二,便记录下来,给自己做一个学习记录,也希望不对地方能够得到补充指点. 1,.托管代码和非托管代码的区别 ...

  4. Clr Via C#读书笔记---I/O限制的异步操作

    widows如何执行I/O操作      构造调用一个FileStream对象打开一个磁盘文件-----FileStream.Read方法从文件中读取数据(此时线程从托管代码转为本地/用户模式代码)- ...

  5. Clr Via C#读书笔记---计算限制的异步操作

    线程池基础 1,线程的创建和销毁是一个昂贵的操作,线程调度以及上下文切换耗费时间和内存资源. 2,线程池是一个线程集合,供应你的用程序使用. 3,每个CLR有一个自己的线程池,线程池由CLR控制的所有 ...

  6. Clr Via C#读书笔记---CLR寄宿和应用程序域

    #1 CLR寄宿: 开发CLR时,Microsoft实际是将他实现成包含在一个dll中的COM服务器.Microsoft为CLR定义了一个标准的COM接口,并为该接口和COM服务器分配了GUID.安装 ...

  7. Clr Via C#读书笔记---程序集的加载和反射

    #1 加载程序集 Assembly.Load: public class Assembly { public static Assembly Load(AssemblyName assemblyRef ...

  8. 读书笔记 C# 接口之浅析

    一.接口可以包含 属性.方法.事件和索引器: 二.接口不能被实例化: 三.一个类可以继承多个接口: 四.接口不能包含方法的实现: 五.继承接口的类必须实现接口中所有成员: 六.显式实现接口的成员,不能 ...

  9. CLR via C# 读书笔记-26.线程基础

    前言 这俩个月没怎么写文章做记录分享,一直在忙项目上线的事情,但是学习这件事情,停下来就感觉难受,clr线程这章也是反复看了好多遍,书读百遍其义自见,今天我们来聊下线程基础 1.进程是什么,以及线程起 ...

随机推荐

  1. 关于Struts2中的ognl-2.6.11.jar和ognl-2.7.3.jar解决思路

    关于Struts2中的ognl-2.6.11.jar和ognl-2.7.3.jar建了一个简单的工程:导入的jar包有六个,包括commons-fileupload-1.2.1.jarcommons- ...

  2. itext-2.1.7.jar

    iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库.通过iText不仅可以生成PDF或rtf的文档,而且可以将XML.Html文件转化为PDF文件. ...

  3. PhoneGap 的存储 API_Web Sql

    一.介绍 此 API 基于 W3C WEB SQL Database Specification 和 W3C Web Storage API Specification. 有些 设备已经提供了对该规范 ...

  4. Mongod启动失败修复方法

    可能的原因:上次服务未正常关闭 1.删除data/db目录下的mongo.lock文件 2.删除/tmp/mongodb-27017.sock文件

  5. 在编译器中调试spark程序处理

    在IDEA中调试spark程序会报错 18/05/16 07:33:51 WARN NativeCodeLoader: Unable to load native-hadoop library for ...

  6. 第六章.MyBatis缓存结构

    一级缓存 测试案例: MyBatisTest.java //缓存 @Test public void testFindCustomerCache1() throws Exception{ SqlSes ...

  7. Jenkins+maven(testng)项目(本地项目配置)

    一.前提: 1. Jenkins下载安装. 2. testng的Maven项目. 二.检测: maven项目自身配置及检测. 1. POM.XML配置文件增加: <build> <p ...

  8. if not

    if not x 在python中的意思是如果x为空 a = [] if not a: print 1 此代码会打印出1 a = [1,2,3] if not a: print 1 此代码不会打印出1 ...

  9. JVM 内部原理

    1.JVM的组成: JVM 由类加载器子系统.运行时数据区.执行引擎以及本地方法接口组成. 2.JVM的运行原理: JVM是java的核心和基础,在java编译器和os平台之间的虚拟处理器.它是一种基 ...

  10. 从零开始学习CocoaPods安装和使用

    从零开始学习CocoaPods安装和使用   转载: Code4App原创:http://code4app.com/article/cocoapods-install-usage http://m.i ...