原贴地址: http://www.cnblogs.com/dudu837/archive/2009/12/07/1618663.html

在实现接口的时候,VS提供了两个菜单,一个是"实现接口",一个是"显式实现接口",它们到底有何不一样呢

我们来比较一下看看

1.首先假设我们有一个接口

public interface ICustomer
{
    void SomeMethod();//接口的所有成员都暗自成为abstract,我们不能为它提供缺省实现,无论这份实现是 多么平淡无奇;接口的成员也都暗自成为public,我们不能以关键字abstract或 public来修改(修饰)其中某个成员。
}

2.如果是"实现接口",那么代码大致如下

public class Customer:ICustomer
{

#region ICustomer 成员

public void SomeMethod()
    {
        throw new NotImplementedException();
    }

#endregion
}

3.如果是"显式实现接口",那么代码大致如下

public class Customer:ICustomer
{

#region ICustomer 成员

void ICustomer.SomeMethod()//显示接口成员的访问级别暗中是public,不允许程序员再加任何修饰符
    {
        throw new NotImplementedException();
    }

#endregion
}

大家看到差别了吧?显式实现的方式,那些方法都会加上一个前缀的。但是,这到底意味着什么呢?

如果是实现接口

public class DAL {
    /// <summary>
    /// 如果我们是直接实现接口的话,那么既可以用接口调用方法,也可以用具体类调用方法
    /// </summary>
    public void GetCustomer() {
        Customer customer = new Customer();
        customer.SomeMethod();
    }

public void GetCustomer2() {
        ICustomer customer = new Customer();
        customer.SomeMethod();
    }
}

如果是显式实现接口

public class DAL {
    /// <summary>
    /// 如果我们是显式实现接口的话,那么要访问里面的方法就只能是通过接口来调用,而不能通过具体类来做
    /// </summary>
    public void GetCustomer() {
        ICustomer customer = new Customer();
        customer.SomeMethod();
    }
}

此外,我们还可以在继承接口的类中同时提供实现接口和显式实现接口两种方式,这样就完成了对一个接口成员提供多份实现实体,访问时可以用类的实例和接口的引用来分别调用这两种实现实体。

现在大部分的系统为了保证扩展性,都广泛地使用接口。显式实现接口,可以隐藏具体类的复杂性。

1.隐式实现的接口

  1. interface IControl
  2. {
  3. void Paint();
  4. }
  5. public class EditBox : IControl
  6. {
  7. public void Paint()
  8. {
  9. Console.WriteLine("Pain method is called!");
  10. }
  11. }
  12. class Test
  13. {
  14. static void Main()
  15. {
  16. EditBox editbox = new EditBox();
  17. editbox.Paint();
  18. ((IControl)editbox).Paint();
  19. Console.ReadKey();
  20. }
  21. }

结果:

Pain method is called!
Pain method is called!

说明:从实例中我们可以看到用隐式实现的接口既可以通过类来访问,也可以通过接口来访问!

2.显式实现的接口

  1. interface IControl
  2. {
  3. void Paint();
  4. }
  5. public class EditBox : IControl
  6. {
  7. void IControl.Paint()
  8. {
  9. Console.WriteLine("IControl.Pain method is called!");
  10. }
  11. }
  12. class Test
  13. {
  14. static void Main()
  15. {
  16. EditBox editbox = new EditBox();
  17. //editbox.Paint();//通过类访问会出错
  18. ((IControl)editbox).Paint();
  19. Console.ReadKey();
  20. }
  21. }

结果:

IControl.Pain method is called!

说明:从实例中我们可以看到用显式实现的接口只能通过接口来访问,如果试图通过类来访问会出错:““ConsoleApplication1.EditBox”并不包含“Paint”的定义。”

3.同时用显/隐式实现接口会怎么样?

  1. interface IControl
  2. {
  3. void Paint();
  4. }
  5. public class EditBox : IControl
  6. {
  7. void IControl.Paint()
  8. {
  9. Console.WriteLine("IControl.Pain method is called!");
  10. }
  11. public void Paint()
  12. {
  13. Console.WriteLine("Pain method is called!");
  14. }
  15. }
  16. class Test
  17. {
  18. static void Main()
  19. {
  20. EditBox editbox = new EditBox();
  21. editbox.Paint();
  22. ((IControl)editbox).Paint();
  23. Console.ReadKey();
  24. }
  25. }

结果:

Pain method is called!
IControl.Pain method is called!

说明:当同时用显/隐式实现接口时,显式才是真正的接口实现方法!

4.结论


多数情况下,我们都是用隐式来实现接口,此时既可以通过类来访问,又可以通过接口来访问,而通过显式实现的接口则只能通过接口来访问,总结一下就是:当显
式实现方式存在时,隐式实现方式就失效了。但这不能表示显式实现方式就不好,当一个类实现的多个接口中具有相同的方法时,用显式方式来专门实现某个接口的
方法时就显得非常有用!

C#中显/隐式实现接口及其访问方法的更多相关文章

  1. 编写高质量代码改善C#程序的157个建议——建议47:即使提供了显式释放方法,也应该在终结器中提供隐式清理

    建议47:即使提供了显式释放方法,也应该在终结器中提供隐式清理 在标准的Dispose模式中,我们注意到一个以~开头的方法,如下: /// <summary> /// 必须,防止程序员忘记 ...

  2. C#实现接口的两种方式:显示实现和隐式实现接口

    本示例声明一个接口IDimensions 和一个类 Box,显式实现了接口成员 GetLength 和 GetWidth. 通过接口实例 dimensions 访问这些成员. interface ID ...

  3. Scala 中的隐式转换和隐式参数

    隐式定义是指编译器为了修正类型错误而允许插入到程序中的定义. 举例: 正常情况下"120"/12显然会报错,因为 String 类并没有实现 / 这个方法,我们无法去决定 Stri ...

  4. JSP——JavaServer Page中的隐式对象(implicit object)、指令(directive)、脚本元素(scripting element)、动作(action)、EL表达式

    目录 1.JSP概述 2.注释(comment) 2.1.JSP注释 2.2.HTML注释 3.隐式对象(implicit object) 3.1.隐式对象清单 3.2.request对象 3.3.o ...

  5. C#中的隐式转换

    你是否考虑过这个问题:为什么不同类型之间的变量可以赋值,而不需要强制转换类型?如: int i = 1; long l = i; object obj = 1; Exception exception ...

  6. Scala 深入浅出实战经典 第62讲:Scala中上下文界定内幕中的隐式参数实战详解

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...

  7. javascript中的隐式类型转化

    javascript中的隐式类型转化 #隐式转换 ## "+" 字符串和数字 如果某个操作数是字符串或者能够通过以下步骤转换为字符串的话,+将进行拼接操作. 如果其中一个操作数是对 ...

  8. 深入探究js中的隐式变量声明

    前两天遇到的问题,经过很多网友的深刻讨论,终于有一个相对可以解释的通的逻辑了,然后我仔细研究了一下相关的点,顺带研究了一下js中的隐式变量. 以下文章中提到的隐式变量都是指没有用var,let,con ...

  9. JavaScript中关于隐式转换的一些总结

    JavaScript运算符中的隐式转换规律:一.递增递减运算符(前置.后置)1.如果包含的是有效数字字符串或者是有效浮点数字符串,则会将字符串转换(Number())为数值,再进行加减操作,返回值的类 ...

随机推荐

  1. 跟Android自带模拟器说拜拜,Mac Genymotion 使用心得

    今天看到网上一片文章点击打开链接,很是激动,套用原作者的话,性能卓越作为历史上最快的Android模拟器(没有之一),秒级开机关机速度足够让你膜拜了(粗略估计5-20s不等),我的Mac上面运行And ...

  2. 剑指OFFER之链表中倒数第k个节点(九度OJ1517)

    题目描述: 输入一个链表,输出该链表中倒数第k个结点.(hint: 请务必使用链表.) 输入: 输入可能包含多个测试样例,输入以EOF结束.对于每个测试案例,输入的第一行为两个整数n和k(0<= ...

  3. I/O流的学习

    一.I/O流 1.判定是输入还是输出我们应该站在程序的立场: 2.判断传输的是字节还是字符,从而决定管道的大小,字节传递是根本,可以传递所有的数据类型,字符传递专门用来传递文本数据,字节主要用来传递二 ...

  4. 目录启动CXF启动报告LinkageError异常以及Java的endorsed机制

    本文纯属个人见解,是对前面学习的总结,如有描述不正确的地方还请高手指正~ Exception in thread "main" java.lang.LinkageError: JA ...

  5. python写的百度贴吧相册下载

    突然想搞个这样的工具,写来写去都不知道在干嘛了,本来两个文件,现在整合在一起了. 乱得不行,懒得整理了,能用就行. 下载部分用了多线程,但是下载一个文件还是用的单线程,也就是没管http头的range ...

  6. JQuery Plugin 2 - Passing Options into Your Plugin

    overriding the default options with user-supplied options and the jQuery extend() method eg: $.fn.pu ...

  7. Educational Codeforces Round 2 C. Make Palindrome 贪心

    C. Make Palindrome Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/600/pr ...

  8. node.js小工具--修改Xcode 'Create by'作者名称

    简介 用Xcode创建源文件时会自动在文件开始位置加入如下注释: // // ISSImageCycleScrollView.m // SoftTravel // // Created by iss1 ...

  9. Android SDK安装时碰到的问题之解决办法

    问题:hostname in certificate didn't match: <dl-ssl.google.com> != <www.google.com> Fetchin ...

  10. Redis 集合(Set)

      Redis的Set是string类型的无序集合.集合成员是唯一的,这就意味着集合中不能出现重复的数据. Redis 中 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1). 集合中最 ...