接口一个被我忽略的地方--接口重定向技术

习惯于用IDE生成接口方法了,右键点击"Implement Interface",生成所有的接口方法声明,还带个Region多方便啊.
今天看<<CLR Vir C#>>时才了解到自己是知其然不知其所有然啊.

 实现接口方法很简单,新手估计也都会,但怎么理解这个过程,不见得所有人都知道

ContractedBlock.gifExpandedBlockStart.gifBase class
None.gifclass Base : IDisposable
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif    
IDisposable Members#region IDisposable Members
InBlock.gif    
public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Base's Dispose");
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif    
#endregion

ExpandedBlockEnd.gif}

None.gif
None.gif

首先我们可以简单的认为Base类里有个Dispose()的方法.这个方法跟是不是IDisposable的成员,先理解为没有关系.当编译这个类的时候,编译器发现它实现了IDisposable接口,于是查找有没有跟其成员IDisposable.Dispose()同名,参数和返回类型完全匹配,并且是public的,如果找到就在IVMap里指向这个方法的入口(我猜的,这地方具体见http://www.microsoft.com/china/MSDN/library/netFramework/netframework/JITCompiler.mspx?mfr=true)如果没有就出个编译错误.

如果找到的方法前面有virtual关键字,编译器仍然认为是匹配的.如何没有virtual关键字,编译器默认的还会为其加上sealed.那么其子类是无法override的.如何想要override父类的Dispose()方法,最好是在Base中定义Dispose()时使用virtual.当然如果我们没有权利改写Base类,我们可以让其子类同样继承自IDisposable,然后改写方法.这点已经有很多人谈论过了,估计大家基本都明白.不了解的可以gongle it!
ContractedBlock.gifExpandedBlockStart.gifDerived
None.gifclass Derived : Base, IDisposable
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Derived's Dispose");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

现在问题来了,我们是真的改写了父类的Dispose()方法吗?
测试一下:
Base c = new Derived();
c.Dispose();
结果你可以发现输出的是: Base's Dispose.当时我觉得很奇怪,后来静下来想想原来可以这么理解.
就如我开始理解接口实现过程一样,对于上面的代码我们可以直接忽略接口的存在,等效如下

ContractedBlock.gifExpandedBlockStart.gifRemove Interface
None.gifclass Base 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif    
public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Base's Dispose");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif
class Derived : Base 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Derived's Dispose");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
None.gif

这样大家应该都知道为什么输出是Base's Dispose,如果不知道可以去查看 "今天你多态了吗"一文,说的很详细了.
回过来看我们刚才的代码,编译的时候有个警告:   'Program.Derived.Dispose()' hides inherited member 'Program.Base.Dispose()'. Use the new keyword if hiding was intended. 
是不是把Dispose()看成只是类的方法更容易理解呢.只是通过接口调用的时候指向了这个方法的入口而已.

我以为如下实现Derived类会更好些,不会让你产生误解,以为Derived  override了Base类的Dispose()方法

ContractedBlock.gifExpandedBlockStart.gif显示实现接口
None.gifclass Derived : Base, IDisposable
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
void IDisposable.Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        Console.WriteLine(
"Derived's Dispose");
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

对于如下代码不要期待能输出Derived's Dispose结果.当然如果CallDispose()传入的参数类型是IDisposable,就当我没说过
static void Main(string[] args)
{
    Derived c = new Derived();
    CallDispose(c);
}
private static void CallDispose(Base b)
{
    b.Dispose();
}

要不然你得这样
private static void CallDispose(Base b)
{
    ((IDispose))b.Dispose();
}
但是你会觉得很别扭.当然 CallDispose(Base b)定义成这样本身就是个不好的设计.

具体大家可以看看<<CLR Vir C#>>14章,我想对于你理解接口实现的整个过程会有莫大的帮助

转载于:https://www.cnblogs.com/anders06/archive/2007/06/12/780719.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364009.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue 学习之路 —— 图片的引入

问题记录&#xff1a;在img中动态设置了src后&#xff0c;图片路径找不到 原因&#xff1a;vue中动态生成的路径无法被url-loader解析到 解决方法&#xff1a; 1、将图片放在static文件夹&#xff0c;然后正常解析 2、将图片使用import方法引入 3、 采用背景图做法&#xff0c;…

跟踪异常–第5部分–使用Spring进行计划

看来我终于快要结束本系列有关使用Spring进行错误跟踪的博客了&#xff0c;对于那些还没有阅读该系列博客的人&#xff0c;我正在编写一个简单但几乎具有工业实力的Spring应用程序&#xff0c;扫描日志文件中的异常&#xff0c;然后生成报告。 在本系列的第一个博客中&#xff…

APP测试理论知识点

什么是APP测试&#xff1f; App测试就是软件工程师对这类应用软件进行功能测试&#xff0c;性能测试&#xff0c;安全性测试以及兼容性测试等。 对于app测试我们一般采用的是黑盒测试方法&#xff0c;也会在必要的时候进行自动化测试以及性能测试&#xff0c;丙炔对于app还会有…

php接口开发 安全_PHP开发api接口安全验证的实例讲解

php的api接口在实际工作中&#xff0c;使用PHP写api接口是经常做的&#xff0c;PHP写好接口后&#xff0c;前台就可以通过链接获取接口提供的数据&#xff0c;而返回的数据一般分为两种情况&#xff0c;xml和json,在这个过程中&#xff0c;服务器并不知道&#xff0c;请求的来源…

Remove Element - LeetCode

目录 题目链接注意点解法小结题目链接 Remove Element - LeetCode 注意点 输入的数组是无序的解法 解法一&#xff1a;使用了erase函数&#xff0c;将等于val的值移除。时间复杂度为O(n) class Solution { public:int removeElement(vector<int>& nums, int val) {fo…

DRF url控制 解析器 响应器 版本控制 分页(常规分页,偏移分页,cursor游标分页)...

url控制第二种写法&#xff08;只要继承了ViewSetMixin&#xff09; url(r^pub/$,views.Pub.as_view({get:list,post:create})), #获取所有记得路由后面加$结束符 #pub/?formatjsonurl(r^pub\.(?P<format>\w)$,views.Pub.as_view({get:list,post:create})), #pu…

[导入]C#好书盘点【月儿原创】

C#好书盘点【月儿原创】 文章来源:http://blog.csdn.net/21aspnet/archive/2007/07/07/1682200.aspx 转载于:https://www.cnblogs.com/zhaoxiaoyang2/archive/2007/07/08/816177.html

岁月如歌,人生如诗

虎跃千山龙腾海&#xff0c;春满家园喜满怀。新的一年&#xff0c;孕育着新的生命&#xff1b;新的一年&#xff0c;掸去了飞雪的扬花&#xff0c;满心的惬意告诉我们&#xff0c;所有的期盼与期望&#xff0c;一切的向往与憧憬正向着我们走近&#xff0c;向着春天融合。 ​ 新…

倒叙输出 php,php foreach正序倒序输出示例代码

实现代码&#xff1a;// 正序foreach($files as $file_num > $file) {if(is_file($directory.$file)){//$file iconv("gb2312","UTF-8",$file); //或者 iconv("gb2312","UTF-8",$value);$date substr($file,0,9);echo ;echo ;ech…

黑色系产业结构

转载于:https://www.cnblogs.com/luoluo-123/p/11143867.html

Smart Form Tutorial(适用新手学习)

发现Smart Form在ECC6中和4.6C相比改变了不少&#xff0c;最近重新研究了一下。help.sap.com上的文档基本上是针对新特性的&#xff0c;不过例子却还是旧的。做个笔记省的以后找不到最新的example。最大的改变在Table上&#xff0c;现在table的header和footer比以前好做了。还是…

执行命令npm install XXX后仍然提示 Cannot find Module XXX

最近遇到一个问题&#xff0c;在服务器上配置完node环境后 执行npm start 命令后提示 Cannot find Module "Jquery" 然后就知道可能没有安装jquery 就继续在当前文件夹下执行 npm install jquery 但是再次执行后却仍然提示 Cannot find Module "Jquery"…

青蛙学Linux—Zabbix Web使用之Zabbix发现功能①自动网络发现

Zabbix的发现功能用于自动发现主机或者监控数据&#xff0c;包括以下三种发现类型&#xff1a; 自动网络发现&#xff08;Network discovery&#xff09;主动客户端自动注册&#xff08;Active agent auto-registration&#xff09;低级别发现&#xff08;low-level discovery&…

php 修改 wordpress,wordpress怎么编辑代码修改页面

wordpress是用PHP写的。PHP是服务器端执行脚本文件。然后到客户端(就是网页)生成html文件。你看到的html代码都是PHP程序在服务器端执行后生成的。若要修改代码主要是看想修改那一部分的内容。然后找到其对应的PHP代码.然后修改。在后台点击-->,就能看见你现在使用的wp主题的…

mpvue tabBar设定 app.json

1.微信小程序&#xff0c;设置src/app.json 中的tabBar 图标选择来自 iconfont 如图所示 小程序显示如下&#xff1a; 转载于:https://www.cnblogs.com/0909/p/11144861.html

JDK 8时代的抽象类与接口

在新的Java 8日期和时间API&#xff1a;Stephen Colebourne的访谈中 &#xff0c; Stephen Colebourne告诉Hartmut Schlosser &#xff1a;“我认为最重要的语言更改不是lambda&#xff0c;而是接口上的静态方法和默认方法。” Colebourne补充说&#xff1a;“添加默认方法消除…

ajax请求拿到多条数据拼接显示在页面中

首先我们拿到的了一坨Json数据 如下 然后通过ajax请求拿到数据 在ajax的success方法中处理和使用数据&#xff1a; 其中包括&#xff1a; 用eval处理这种数据 var outStr eval(( data.data )); 用循环取出数据并使用 $.each(outStr,function(index){ console.log(outStr[i…

在IntelliJ IDEA中为不同的数据源着色

IntelliJ IDEA中的数据库插件是使用数据库中数据的有用工具。 只要我们有了JDBC驱动程序来连接数据库&#xff0c;就可以配置数据源。 然后&#xff0c;我们可以运行查询&#xff0c;检查表的内容并使用数据库工具窗口更改数据。 具有多个数据源&#xff08;例如开发和测试环境…

[蓝桥杯]ALGO-185.算法训练_Trash Removal

题目描述&#xff1a; 代码如下&#xff1a; 1 #include <algorithm>2 #include <cstdio>3 #include <cstdlib>4 #include <cmath>5 #include <cstring>6 #include <iostream>7 #define INF 0x7fffffff8 using namespace std;9 10 typed…

从客户端...中检测到有潜在危险的 Request.Form 值

在.net中&#xff0c;Request时出现有HTML、Javascript等字符串时&#xff0c;系统会认为是危险值&#xff0c;运行显示“从客户端……中检测到有潜在危险的Request.Form值”这样的错。解决办法&#xff1a; &#xff08;1&#xff09; 在.aspx文件头中加入这句&#xff1a; …