C# 8.0 中开启默认接口实现
当你升级到 C# 8.0 和 .NET Core 3.0 之后,你就可以开始使用默认接口实现的功能了。
从现在开始,你可以在接口里面添加一些默认实现的成员,避免在接口中添加成员导致大量对此接口的实现崩溃。
本文内容
最低要求
要写出并且正常使用接口的默认实现,你需要:
- C# 8.0
- .NET Core 3.0
- Visual Studio 2019 Preview (16.1 以上版本)
下载安装 Visual Studio 2019 Preview 版本
- 前往下载安装 Visual Studio Preview
开启 .NET Core 3.0 的支持
对于预览版的 Visual Studio 2019 来说,.NET Core 的预览版是默认打开且无法关闭的,所以不需要关心。
开启 C# 8.0 支持
请设置你项目的属性,修改 C# 语言版本为 8.0(对于预览版的语言来说,这是必要的):

或者直接修改你的项目文件,加上 LangVersion 属性的设置,设置为 8.0。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
</Project>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
默认接口实现
以前的做法
比如,我们现在有下面这样一个简单的接口:
public interface IWalterlv
{
void Print(string text);
}
- 1
- 2
- 3
- 4
这个接口被大量实现了。
现在,我们需要在接口中新增一个方法 DouBPrint,其作用是对 Print 方法进行标准化,避免各种不同实现带来的标准差异。于是我们新增一个方法:
public interface IWalterlv
{
void Print(string text);
++ void DouBPrint(string text);
}
- 1
- 2
- 3
- 4
- 5
- 6
然而我们都知道,这样的修改是破坏性的:
- 会使得所有实现这个接口的代码全部失败(无法编译通过,或者运行时抛出异常)
- 我们依然很难将接口的实现标准化,靠文档来规约
默认接口实现
那么现在,我们可以这样来新增此方法:
public interface IWalterlv
{
void Print(string text);
-- void DouBPrint(string text);
++ public void DouBPrint(string text) => Print($"Walterlv 逗比 {text}");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
在使用此方法来定义此接口中的方法后,那些没来得及实现此方法的类型也可以编译通过并获得标准化的实现。
class Program
{
static void Main(string[] args)
{
IWalterlv walterlv = new Foo();
walterlv.DouBPrint("walterlv");
}
}
public class Foo : IWalterlv
{
public void Print(string text)
{
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
当然,对于 Foo 类型来说,实现也是可以的:
public class Foo : IWalterlv
{
public void Print(string text)
{
}
public void DouBPrint(string text) => Print($"Walterlv 逗比 {text}");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
静态字段和方法
除此之外,在接口中还可以编写静态字段和静态方法,这可以用来统一接口中的一些默认实现。
意味着,如果类没有实现接口中带有默认实现的方法,那么具有默认的实现;而如果类中打算实现接口中的带有默认实现的方法,那么也可以调用接口中的静态方法来进行实现。
public interface IWalterlv
{
void Print(string text);
-- public void DouBPrint(string text) => Print($"Walterlv 逗比 {text}");
++ public void DouBPrint(string text) => DefaultDouBPrint(this, text);
++
++ private static readonly string _name = "walterlv";
++
++ protected static void DefaultDouBPrint(IWalterlv walterlv, string text)
++ => walterlv.Print($"{_name} 逗比 {text}");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
然后,对于实现方,则需要使用接口名来调用接口中的静态成员:
public class Foo : IWalterlv
{
public void Print(string text)
{
}
-- public void DouBPrint(string text) => Print($"Walterlv 逗比 {text}");
++ public void DouBPrint(string text)
++ {
++ // Do Other things.
++ IWalterlv.DefaultDouBPrint(this, text);
++ }
++ }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
参考资料
- Default implementations in interfaces - .NET Blog
- Visual Studio 2019 version 16.1 Preview 3 - The Visual Studio Blog
- Safely update interfaces using default interface members in C# - Microsoft Docs
我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。
如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
C# 8.0 中开启默认接口实现的更多相关文章
- C#8.0 中使用默认接口成员更新接口
连载目录 [已更新最新开发文章,点击查看详细] 从 .NET Core 3.0 上的 C# 8.0 开始,可以在声明接口成员时定义实现. 最常见的方案是安全地将成员添加到已经由无数客户端发布并使 ...
- [译]C#8.0中一个使接口更加灵活的新特性-默认接口实现
9月份的时候,微软宣布正式发布C#8.0,作为.NET Core 3.0发行版的一部分.C#8.0的新特性之一就是默认接口实现.在本文中,我们将一起来聊聊默认接口实现. 众所周知,对现有应用程序的接口 ...
- 在Tomcat7.0中设置默认服务器和不加端口名访问
前言 昨天买了域名,服务器,然后搭建了环境,然后想他通过默认的端口,不用端口就访问. 设置WEB项目的欢迎页 在WEB-INF文件夹下有个web.xml文件(最近新建的项目不包含此文件,可以手动新建) ...
- Springboot2.0中jpa默认创建的mysql表为myisam引擎问题
使用Springboot2.0后,使用jpa操作mysql数据库时,默认创建的表的引擎是myisam,myisam是不能加外键的,找了一些资源,最终可以用此方法解决! yml格式: spring: j ...
- IHostingEnvironment VS IHostEnvironment - .NET Core 3.0中的废弃类型
原文: https://andrewlock.net/ihostingenvironment-vs-ihost-environment-obsolete-types-in-net-core-3/ 作者 ...
- C# 8: 默认接口方法
翻译自 John Demetriou 2018年8月4日 的文章 <C# 8: Default Interface Methods>[1],补充了一些内容 C# 8 之前 今天我们来聊一聊 ...
- JDK8.0接口中的默认方法和静态方法
我们在接口中通常定义的方法是抽象方法,即没有方法体,只有返回值类型和方法名:(public abstract) void Method(); 类在实现接口的时候必须重写抽象方法才可以 jdk8中新加的 ...
- Java6.0中Comparable接口与Comparator接口详解
Java6.0中Comparable接口与Comparator接口详解 说到现在,读者应该对Comparable接口有了大概的了解,但是为什么又要有一个Comparator接口呢?难道Java的开发者 ...
- Java 8 接口中的默认方法与静态方法
Java 8 接口中的默认方法与静态方法 1. 接口中的默认方法 允许接口中包含具有具体实现的方法,该方法称"默认方法",默认方法使用用 default 关键字修饰. public ...
随机推荐
- 【POJ1426】Find The Multiple
本题传送门 本题知识点:深度优先搜索 | 宽度优先搜索 题意很简单,让我们找一个只有1和0组成的十位数是n的倍数的数. 这题一开始吓到我了--因为Output里说输出的长度最长不超过100位???那是 ...
- 聊聊Dubbo(六):核心源码-Filter链原理
转载:https://www.jianshu.com/p/6dd76ce7338f 0 前言 对于Java WEB应用来说,Spring的Filter可以拦截WEB接口调用,但对于Dubbo接口,Sp ...
- SNF快速开发平台2020版
SNF快速开发平台分如下子平台: 1.CS快速开发平台 2.BS快速开发平台 3.H5移动端快速开发平台 4.软件开发机器人平台 配置型开发零编程 SNF快速开发平台是一个比较成熟的.net领域的商业 ...
- linux编译Qt+mysql驱动+可执行文件移植目标机
前言: 如果希望自己的Qt/C++程序在目标机上运行,最简单的方法就是在目标机上安装一个Qtcreater[Qtxxx.run],然后编译release的可执行文件,直接拉起即可. 但是有些环境情况比 ...
- 两分钟观看 nodejs、 iojs、 npmjs 之间的狗血剧情
开门大吉,欢迎光临.这是 乐玩nodejs npm工具库 微信公众号的第一篇文章,那就先来说说 nodejs/npm 的小秘密,话不多说,赶快开始: 通过一个时间线简要描述下 2008 年 V8 引擎 ...
- python os.popen('xxx.py') 遇到的坑 (No Child Processes)
1.调用系统库 platform.system() 报错: 2.os.popen() 打开的文件流未关闭也会出现这种错误. f = os.popen() f.read() f.close() 问题复现 ...
- 定制flask-admin的主页
flask也用了很久了,一般配合flask-admin设置后台. 但是flask-admin设置的都是自己加入的,对某些model进行管理. 下面介绍如何定制flask-admin的首页. 原来我们引 ...
- 【数据集】FDDB-Face Detection Data Set and Benchmark
前言 参考 1. FDDB官网: 完
- (转) C#使用ODP.NET(Oracle.ManagedDataAccess.dll)操作Oracle数据库
原贴链接:https://www.cnblogs.com/mq0036/p/11052359.html C#使用ODP.NET(Oracle.ManagedDataAccess.dll)操作Oracl ...
- Mac系统Android 命令行签名
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore keystore文件位置 -signedjar ~/afterSign ...
