C#隐式/显示实现接口方法详解

接口定义了一系列的行为规范,为类型定义一种Can-Do的功能。例如,实现IEnumerable接口定义了GetEnumerator方法,用于获取一个枚举数,该枚举数支持在集合上进行迭代,也就是我们常说的foreach。接口只是定义行为,具体的实现需要由具体类型负责,实现接口的方法又分为隐式实现与显示实现。

一、隐式/显示实现接口方法

  简单的说,我们平时“默认”使用的都是隐式的实现方式。例如:

interface ILog
{
  void Log();
}

public class FileLogger : ILog
{
  public void Log()
  {
    Console.WriteLine("记录到文件!");
  }
}

  隐式实现很简单,通常我们约定接口命名以 I 开头,方便阅读。接口内的方法不需要用public,编译器会自动加上。类型中实现接口的方法只能是public,也可以定义成虚方法,由子类重写。现在看显示实现的方式:

public class EventLogger : ILog
{
  void ILog.Log()
  {
    Console.WriteLine("记录到系统事件!");
  }
}

  与上面不同的是,方法用了ILog指明,而且没有(也不能有)public或者private修饰符。

  除了语法上的不同,调用方式也不同,显示实现只能用接口类型的变量来调用,如:

FileLogger fileLogger = new FileLogger();
fileLogger.Log(); //正确
EventLogger eventLogger = new EventLogger();
eventLogger.Log(); //报错
ILog log = new EventLogger();
log.Log(); //正确

二、何时使用

  1. c#允许实现多个接口,如果多个接口定义了相同的方法,可以用显示实现的方式加以区分,例如:

interface ISendable
{
  void Log();
}

public class EmailLogger : ILog, ISendable
{
  void ILog.Log()
  {
    Console.WriteLine("ILog");
  }

  void ISendable.Log()
  {
    Console.WriteLine("ISendable");
  }
}

  2. 增强编译时的类型安全和避免值类型装箱

  有了泛型,我们自然可以做到编译时的类型安全和避免值类型装箱的操作。但有时候可能没有对应的泛型版本。例如:IComparable(这里只是举例,实际有IComparable<T>)。如:

interface IComparable
{
  int CompareTo(object obj);
}

struct ValueType : IComparable
{
  private int x;
  public ValueType(int x)
  {
    this.x = x;
  }

  public int CompareTo(object obj)
  {
    return this.x - ((ValueType)obj).x;
  }
}

  调用:

ValueType vt1 = new ValueType(1);
ValueType vt2 = new ValueType(2);
Console.WriteLine(vt1.CompareTo(vt2));

  由于形参是object,上面的CompareTo会发生装箱;而且无法获得编译时的类型安全,例如我们可以随便传一个string,编译不会报错,等到运行时才抛出InvalidCastException。使用显示实现接口的方式,如:

public int CompareTo(ValueType vt)
{
  return this.x - vt.x;
}

int IComparable.CompareTo(object obj)
{
  return CompareTo((ValueType)obj);
}

  再次执行上面的代码,就不会发生装箱操作,而且可以获得编译时的类型安全了。但是如果我们用接口变量调用,就会再次发生装箱并丧失编译时的类型安全检测能力。

IComparable vt1 = new ValueType(1); //装箱
ValueType vt2 = new ValueType(2);
Console.WriteLine(vt1.CompareTo(vt2)); //再次装箱

三、缺点

  1. 显示实现只能用接口类型变量调用,会给人的感觉是某类型实现了该接口却无法调用接口中的方法。特别是写成类库给别人调用时,显示实现的接口方法在vs中按f12都不会显示出来。(这点有人在csdn提问过,为什么某个类型可以不用实现接口方法)

  2. 对于值类型,要调用显示实现的方法,会发生装箱操作。

  3. 无法被子类继承使用。

以上就是C#显示实现接口的全部内容,希望对大家的学习有所帮助。

(0)

相关推荐

  • C#中的ICustomFormatter及IFormatProvider接口用法揭秘

    最近在学习IFormatProvider接口的用法时,在网络上找了段实例代码(具体哪个网站不记得了,就不给出链接了),通过研究实例代码,初步了解了IFormatProvider接口的用法. 在学习代码之前,我们先来了解一下本例中使用到的两个接口ICustomFormatter及IFormatProvider. 查看MSDN,得到以下关于ICustomFormatter及IFormatProvider接口的说明. 接口ICustomFormatter:定义一种方法,它支持自定义设置对象的值的格式.

  • C#判断一个类是否实现了某个接口3种实现方法

    B为一个类,ISay为一个接口. 方法1: 复制代码 代码如下: B b = new B();   if (b.GetType().GetInterface("ISay") != null)             {                 //如果实现了接口"ISay",...             } 方法2: 复制代码 代码如下: B b = new B();  if (b is ISay)             {               

  • C#中实现判断某个类是否实现了某个接口

    有时我们需要判断某个类是否实现了某个接口(Interface),比如在使用反射机制(Reflection)来查找特定类型的时候. 简单来说,可以使用Type.IsAssignableFrom方法: typeof(IFoo).IsAssignableFrom(bar.GetType()); typeof(IFoo).IsAssignableFrom(typeof(BarClass)); 从字面意思可以看出,IsAssignableFrom表示BarClass类型能否赋值给IFoo接口,所以它返回t

  • C#接口实现方法实例分析

    本文实例讲述了C#接口实现方法.分享给大家供大家参考.具体如下: 在讲解C#实现接口的实例解析之前我们来看看C#接口的定义,如果一个类派生于一个接口,它就会执行某些函数.并不是所有的面向对象语言都支持接口,所以本节将详细介绍C#实现接口的问题. C#实现接口注意: 熟悉COM的开发人员应注意,尽管在概念上C#接口类似于COM接口,但它们是不同的,底层的结构不同,例如,C#接口并不派生于IUnknown.C#接口根据.NET函数提供了一个契约.与COM接口不同,C#接口不代表任何类型的二进制标准.

  • C#接口interface用法实例

    本文实例讲述了C#接口interface用法.分享给大家供大家参考.具体如下: using System; //example of interfaces public class Animals { //simple interface interface IAnimal { void Breathes(); } //interfaces can inherent from other interfaces interface IMammal : IAnimal { int HairLengt

  • C#开发微信公众号接口开发

    具体实现方式不多说了,请看下文 一.前言 当下微信公众号几乎已经是每个公司必备的,但是大部分微信公众账号用户体验都欠佳,特别是涉及到用户绑定等,需要用户进行复杂的操作才可以和网站绑定,或者很多公司直接不绑定,而是每次都让用户填写账号密码.作为微信接口开发人员我们知道网页授权可以用作微信网页用作安全登录,带参数二维码的使用用作记录用户来源,模板消息用作购物消费等消息的通知,但是很少看到有综合利用这些高级接口做出体验比较好的公众账号,这里分享一些我开发的用户绑定和验证码的一些心得.所需要的接口有基础

  • C# 接口的隐式与显示实现及适应场景

    以前在用到接口时,从来没注意到接口分为隐式实现与显示实现.昨天在浏览博客时看到相关内容,现在根据自己的理解记录一下,方便日后碰到的时候温习温习. 通俗的来讲,"显示接口实现"就是使用接口名称作为方法名的前缀;而传统的实现方式称之为:"隐式接口实现".费话不说,例子如下: 复制代码 代码如下: interface IAnimal { void Dog(); } class Animal:IAnimal { public void Dog() { Console.Wri

  • C#动态webservice调用接口

    C#动态webservice调用接口 using System; using System.Collections; using System.IO; using System.Net; using System.Text; using System.Xml; using System.Xml.Serialization; namespace Hishop.Plugins { /// <summary> /// 利用WebRequest/WebResponse进行WebService调用的类

  • 通过C#实现自动售货机接口

    下面分几部分介绍C#实现自动售货机接口的方法,代码写的非常详细,不懂的地方有注释可以参考下. MachineJP类: 第1部分:串口初始化,串口数据读写 using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Syst

  • C#隐式/显示实现接口方法详解

    接口定义了一系列的行为规范,为类型定义一种Can-Do的功能.例如,实现IEnumerable接口定义了GetEnumerator方法,用于获取一个枚举数,该枚举数支持在集合上进行迭代,也就是我们常说的foreach.接口只是定义行为,具体的实现需要由具体类型负责,实现接口的方法又分为隐式实现与显示实现. 一.隐式/显示实现接口方法 简单的说,我们平时"默认"使用的都是隐式的实现方式.例如: interface ILog { void Log(); } public class Fil

  • Android操作SQLite数据库(增、删、改、查、分页等)及ListView显示数据的方法详解

    本文实例讲述了Android操作SQLite数据库(增.删.改.查.分页等)及ListView显示数据的方法.分享给大家供大家参考,具体如下: 由于刚接触android开发,故此想把学到的基础知识记录一下,以备查询,故此写的比较啰嗦: 步骤如下: 一.介绍: 此文主要是介绍怎么使用android自带的数据库SQLite,以及把后台的数据用ListView控件显示 二.新建一个android工程--DBSQLiteOperate 工程目录: 三.清单列表AndroidManifest.xml的配置

  • Python实现matplotlib显示中文的方法详解

    本文实例讲述了Python实现matplotlib显示中文的方法.分享给大家供大家参考,具体如下: [注意] 可能与本文主题无关,不过我还是想指出来:使用matplotlib库时,下面两种导入方式是等价的(我指的是等效,当然这个说法可以商榷:) import matplotlib.pyplot as plt import pylab as plt [效果图] [方式一]FontProperties import matplotlib.pyplot as plt from matplotlib.f

  • Django框架实现分页显示内容的方法详解

    本文实例讲述了Django框架实现分页显示内容的方法.分享给大家供大家参考,具体如下: 分页 1.作用 数据加载优化 2.前端引入bootstrap样式: {# 引入bootstrap样式的cdn资源 #} <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="external nofollow" rel="stylesheet">

  • 在C# 8中如何使用默认接口方法详解

    前言 C# 8 中新增了一个非常有趣的特性,叫做 默认接口方法 (又称虚拟扩展方法),这篇文章将会讨论 C# 8 中的默认接口方法以及如何使用. 在 C# 8 之前,接口不能包含方法定义,只能在接口中定义方法签名,还有一个就是接口的成员默认是 public 和 abstract , 在 C# 8 之前,接口不能包含字段,也不能包含private, protected, 或者 internal 的方法成员.如果你在接口中引入了一个新成员,默认情况下你必须更新实现该接口的所有子类. 在 C# 8 中

  • Java如何提供给第三方使用接口方法详解

    目录 前言 接口Controller 接口幂等性校验 实现类ServiceImpl 第三方调用接口Api实现类 生成签名工具类 HttpCilent工具类 附:分享一个获取IP工具类 总结 前言 相信有很多小伙伴,在日常的开发中都有遇到过需要调用第三方接口的需求吧,但是自己有没有写过接口提供给第三方使用呢,常规的都是我们调用别人的接口,但是自己需要开发接口提供给第三方使用的场景应该不是很多,很多小伙伴可能会想不就开发一个接口对外开放嘛岂不是很简单,但是在开发接口对外开放,我们需要考虑一个问题,没

  • 编写php应用程序实现摘要式身份验证的方法详解

    通基本身份认证一样,也可以使用PHP网页处理HTTP请求报头字段来匹配摘要式身份验证信息.例如下边的代码使用header()函数要求客户端使用Digest验证,它在HTTP消息报头中增加了一个WWW-Authenticate字段:header('WWW-Authenticate:Digest Realm="MyRealm",nonce="47alf7cf25ce7",algorithm=MD5,qop="auth"');-------------

  • plotly分割显示mnist的方法详解

    目录 加载mnist plotly显示多个mnist样本 plotly显示单个图片 mnist单样本分拆显示 mnist单样本错误的分拆显示 总结 加载mnist import numpy def loadMnist() -> (numpy.ndarray,numpy.ndarray,numpy.ndarray,numpy.ndarray): """ :return: (xTrain,yTrain,xTest,yTest) """ glob

  • JAVA发送http get/post请求,调用http接口、方法详解

    三个例子 -JAVA发送http get/post请求,调用http接口.方法 例1:使用 HttpClient (commons-httpclient-3.0.jar jar下载地址:http://xiazai.jb51.net/201904/yuanma/commons-httpclient-3.0.rar import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOE

  • default怎么修饰接口中的方法详解

    一.default修饰接口中的方法 在实现HandlerInterceptor接口时,我发现不实现HandlerInterceptor接口的方法也不会报错 仔细想来,还是我对接口的理解不清晰. 打开源码发现HandlerInterceptor接口中的方法都是default 在以前的接口编写中,我总是省略权限修饰符,因为在接口中的方法中默认是public abstract. 那么再来对接口进行总结. 那么也就是说,实现类要覆盖接口中的抽象方法就能实例化,而HandlerInterceptor接口中

随机推荐