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. 设置 jsp 表格相邻两行的颜色不一样

    转载网址:https://zhidao.baidu.com/question/134905332.html?fr=iks&word=for+%28var+i%3D0%3Bi%3CTable.r ...

  2. 安装最新版的wampserver,可以兼容php5和php7

    本文介绍的wamp是Windows+Apache+MySQL+PHP+phpMyAdmin,主要应用于开发环境[一键安装包,简单好用]. 这是运行在Windows系统下的官方安装包,可以快速的搭建属于 ...

  3. mac 系统安装selenium注意事项

    mac最新系统:OS X EI Captian python: 本机自带的python2.7. (本来想升级3.5,觉得太复杂,放弃了) pip: https://pypi.python.org/py ...

  4. halcon 数字转字符串实现循环读取图片

    1.将字符转换为数字 tuple_number (StringImageIndex,IntImageIndex) 2.将数字转换为字符 tuple_string (IntImageIndex, '0' ...

  5. StringJoiner

    示例一 public class StringJoinerTest1 { public static void main(String[] args) { StringJoiner joiner = ...

  6. 启动memcache

    "D:\SOFT\memcached-1.4.5-amd64\memcached-amd64\memcached.exe"

  7. 前端基础-CSS如何布局以及文档流

    一. 网页布局方式 二. 标准流 三. 浮动流 四. 定位流 一. 网页布局方式 1.什么是网页布局方式 布局可以理解为排版,我们所熟知的文本编辑类工具都有自己的排版方式, 比如word,nodpad ...

  8. unittest单元测试框架之测试结果输出到外部文件(四)

    1.test_suit执行测试用例及输出结果前 添加如下代码(打开会新建d:/result.txt文件): with open("d:\\result.txt","a&q ...

  9. [Medium翻译]RESTful API权威设计指南-设计更好的API

    本文为授权译文.希望查看原文的同学请戳链接:https://hackernoon.com/restful-api-design-step-by-step-guide-2f2c9f9fcdbf 对于我们 ...

  10. mybatis使用*号查询数据丢失问题

    使用*号的SQL语句:select * from 表名 在开发过程中可能你会发现使用mybatis框架爱作为持久层时,写的SQL语句在工具里面查询数据是可以查到想要的数据的,但是在项目中会出现数据丢失 ...