谨慎使用显式接口方法实现
来源:互联网 发布:云计算的概念? 编辑:程序博客网 时间:2024/06/03 17:54
上一篇文章我们讲解了隐式和显式接口背后发生的故事(http://blog.csdn.net/u010533180/article/details/72954192),而且要慎用显式接口方法,本篇文章讲讲显式接口方法带来的一些问题。
显式接口方法 EIMI 最主要的问题如下:
1) 没有文档解释一个类型具体如何实现一个EIMI,也没有Microsof Visual Studio 智能感知支持。
2) 值类型的实例在转型为接口时需要进行装箱操作。
3) EIMI 方法不能由派生类型调用。
下面详细说说这些问题。
在.NET Framework 参考文档中查看一个类型的方法时,会列出显式接口方法实现(EIMI),单没有提供类型特有的帮助,只能看到接口方法的常规性帮助。例如:Int32类型的文档只是说它实现了IConvertible 接口的所有方法。但是开发人员不能直接在一个Int32上调用一个IConvertible 方法。例如,下面的代码无法编译:
public static void Main() { Int32 x = 5; Single s = x.ToSingle(null); }
会报如下的错误:
错误 5 “int”不包含“ToSingle”的定义,并且找不到可接受类型为“int”的第一个参数的扩展方法“ToSingle”(是否缺少 using 指令或程序集引用?)
从上述各图中明显看出Int32类型没有定义ToSingle方法,单事实上这个方法已经定义了。
要想在一个Int32上调用ToSingle,首先必须先把这个Int32转型为IConvertible。
public static void Main() { Int32 x = 5; Single s = ((IConvertible) x).ToSingle(null); }
这时还需要进行转型操作,将Int32值类型转型为IConvertible,还要对值类型进行装箱,这样既浪费内存,也损害性能。这是之前提到的第二个大问题。
我们看如下代码:
class Base : IComparable { #region IComparable 成员 int IComparable.CompareTo(object obj) { Console.WriteLine("Base's CompareTo"); return 0; } #endregion } class Derived : Base, IComparable { public int CompareTo(Object o) { Console.WriteLine("Derived's CompareTo"); base.CompareTo(o); return 0; } }
上述代码出现如下错误:
错误 6 “NowCoderProgrammingProject.Base”并不包含“CompareTo”的定义
Base类没有提供一个可以调用的公共或受保护的CompareTo方法,它提供的是一个只能用IComparable类型的变量来调用CompareTo方法,可把上述代码修改为如下方法:
class Base : IComparable { #region IComparable 成员 int IComparable.CompareTo(object obj) { Console.WriteLine("Base's CompareTo"); return 0; } #endregion } class Derived : Base { public int CompareTo(Object o) { Console.WriteLine("Derived's CompareTo"); IComparable c = this; c.CompareTo(o); return 0; } } class EIMI { public static void Main() { Derived d= new Derived(); object o= ""; d.CompareTo(o); } }
运行输出结果如下:
Derived's CompareToBase's CompareTo
上述代码之所以能够运行是因为在Dervied类中去掉了IComparable 接口的继承,通过转型为IComparable 然后调用对应的CompareTo方法。但是有时候,不能简单的将接口从类型中去除,因为希望派生类实现一个接口方法。解决这个问题的方法是在基类中除了提供一个被选为显式实现的接口方法,还要提供一个虚方法。然后Derived类可以重写虚方法。看如下代码:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace NowCoderProgrammingProject{ class Base : IComparable { #region IComparable 成员 /// <summary> /// 显示实现接口方法EIMI /// </summary> /// <param name="obj"></param> /// <returns></returns> int IComparable.CompareTo(object obj) { Console.WriteLine("Base's CompareTo"); return VirtualCompareTo(obj);//调用虚方法 } #endregion /// <summary> /// 用于派生类的虚方法 /// </summary> /// <param name="obj"></param> /// <returns></returns> public virtual int VirtualCompareTo(object obj) { Console.WriteLine("Base's Virtual CompareTo"); return 0; } } class Derived : Base,IComparable { /// <summary> /// 复写父类的方法,也是接口方法的实现 /// </summary> /// <param name="o"></param> /// <returns></returns> public override int VirtualCompareTo(Object o) { Console.WriteLine("Derived's CompareTo"); return base.VirtualCompareTo(o);//调用父类的虚方法 } } class EIMI { public static void Main() { Derived d= new Derived(); object o= ""; d.VirtualCompareTo(o); } }}
运行结果如下:
Derived's CompareToBase's Virtual CompareTo
注意前面将虚方法定义成公共方法,但有的情况下,可能需要定义为受保护的方法。把方法定义为受保护是可以的,但必须进行一些小改动。 通过上述代码的讨论清楚的证明了务必谨慎使用EIMI。许多开发人员就肆无忌惮的使用EIMI。千万不要这样做!EIMI在某些情况下确实有用,但是应该尽量避免使用,因为它们使类型的使用变的困难很多。
下面的例子是把EIMI更改受保护的方法,然后需要增加一个新的公共方法,因为受保护的方法只能在本类以及子类中才能调用:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace NowCoderProgrammingProject{ class Base : IComparable { #region IComparable 成员 /// <summary> /// 显示实现接口方法EIMI /// </summary> /// <param name="obj"></param> /// <returns></returns> int IComparable.CompareTo(object obj) { Console.WriteLine("Base's CompareTo"); return VirtualCompareTo(obj);//调用虚方法 } #endregion /// <summary> /// 用于派生类的虚方法 /// </summary> /// <param name="obj"></param> /// <returns></returns> protected virtual int VirtualCompareTo(object obj) { Console.WriteLine("Base's Virtual CompareTo"); return 0; } } class Derived : Base,IComparable { /// <summary> /// 复写父类的方法,也是接口方法的实现 /// </summary> /// <param name="o"></param> /// <returns></returns> protected override int VirtualCompareTo(Object o) { Console.WriteLine("Derived's CompareTo"); return base.VirtualCompareTo(o);//调用父类的虚方法 } public int ProtectedCompareTo(object o) { Console.WriteLine("Derived's Protected CompareTo"); return VirtualCompareTo(o);//调用父类的虚方法 } } class EIMI { public static void Main() { Derived d= new Derived(); object o= ""; d.ProtectedCompareTo(o); } }}
运行结果如下:
Derived's Protected CompareToDerived's CompareToBase's Virtual CompareTo
参考来源 CLR VIA C# 第三版 13.10
- 谨慎使用显式接口方法实现
- 74-谨慎的实现serializable接口
- 谨慎使用SocketChannel的read方法
- AndroidStudio中使用Kotlin--实现接口方法
- 2015070304 - EffactiveJava笔记 - 第54条 谨慎使用本地方法
- 建议89:在并行方法体中谨慎使用锁
- 调用成熟接口、谨慎使用未知接口------遇到问题时, 不一定要死死纠缠原因
- 谨慎重置equals方法
- 谨慎使用mailto标签
- 谨慎使用OpenSessionInViewFilter
- 谨慎使用百度音乐盒
- 谨慎使用 private inheritance
- union的谨慎使用
- 谨慎使用IsMissing函数
- 全局变量应谨慎使用
- 谨慎使用 CSS Sprites
- 谨慎使用USES_CONVERSION
- 谨慎使用null
- 配置虚拟主机
- 推荐大家使用的CSS书写规范、顺序
- ECMAScript6(11):Set 与 Map
- JMeter 命令行选项
- Git fetch和git pull的区别
- 谨慎使用显式接口方法实现
- strtok函数的用法
- 数据库集群+好处+原理图
- Centos7安装MySQL
- 学习July博文总结——支持向量机(SVM)的深入理解(下)
- 每天一个Linux命令(44):top命令
- Git之使用GitHub搭建远程仓库
- cast强制类型转换
- 每天一个Linux命令(45):free命令