C# 8.0 的默认接口方法

  • 2019 年 10 月 31 日
  • 笔记

例子

直接看例子

有这样一个接口: 

public interface IPerson  2 references  { get; set;  string  Name  2 references  { get; set; }  int  Age

 

然后有三个它的实现类: 

public class Teacher  IPerson  6 references  public string Name { get; set;  3 references  public int Age { get; set; }  I reference  public class Student  IPerson  6 references  public string Name { get; set;  3 references  public int Age { get; set; }  I reference  public class Actor  IPerson  6 references  public string Name { get; set;  3 references  public int Age { get; set; }

 

然后在main方法里面调用: 

static void Elgin(stringC]  gx•gs  new Teacher();  var teacher =  new Student();  var student =  new Actor();  var actor =  Console . WriteLine( teacher . Name);  Console . WriteLine(student . Name);  Console . WriteLine( actor . Name);

截至目前,程序都可以成功的编译和运行。 

 

IPerson接口变更 

突然,我想对所有的人类添加一个新的特性,例如,添加一个自我介绍的方法,所以我在IPerson里添加了Introduce()这个方法: 

public interface IPerson  S references  { get; set;  string  Name  3 references  { get; set; }  int  Age  O references  Introduce()  void

 

现在再次Build一下项目,肯定会失败的: 

irror List  Entire Solution  Code  O CS0535  O CS0535  O CS0535  Description  'Teacher' does not implement interface member 'IPerson.IntroduceO'  'Student' does not implement interface member 'IPerson.IntroduceO'  'Actor' does not implement interface member 'IPerson.IntroduceO'

因为这个方法在三个实现类里面都没有实现。 

 

使用默认的实现来更新接口 

如果在C# 8.0以前,我们肯定需要把三个实现类都实现一下这个Introduce() 方法。而在C# 8.0里,我们可以在IPerson接口里做一个默认的方法实现: 

public interface IPerson  7 references  string Name { get; set;  4 references  int Age { get; set; }  O references  Introduce()  void  Console.WriteLine($"I'm  {Name} ,  {Age} years old. " ) ,

 

再次Build之后,您会发现就没有错误了: 

utput  how output from: Build  ConsoleÅppl, on: Debug Any CPU  started: projec  D: OlCorEoI•App1. 811  succeeded. O O

 

而且我们也可以在所有的实现类上正常的调用这个方法: 

static void Mgin(stringC]  gx•gs  var  var  var  var  new Teacher();  teacher =  new Student();  student =  new Actor();  actor =  C] { teacher,  new IPerson  persons =  student,  actor } ;  foreach (var person in persons)  person . Introduce( ) ;

 

I'm  I'm  I'm  years old.  years old.  years old.

我没有设置任何属性,但是结果是没问题的。 

 

但是,不可以直接在实现类上调用该方法,例如这样写就会报错: 

var  var  var  new Teacher();  teacher =  new Student();  student =  new Actor();  actor =  teacher . Introduce( ) ;

这是因为Teacher这个实现类并没有定义Introduce()这个方法。 

在前面的例子的里,我是通过IPerson接口调用的这个方法,这是没有问题的,因为IPerson这个接口定义了这个方法。 

 

接口的静态成员 

上面例子的输出是这样的: 

I'm  I'm  I'm  years old.  years old.  years old.

 

而我想让输出有默认的名字和年龄,在C# 8.0里面,我们可以这样做,添加静态字段(field)和静态方法: 

public interface IPerson  private static string DefaultName -  private static int 20;  O references  "Jane Doe";  SetNameAndAge(string name, int age)  static void  DefaultName  = name;  DefaultAge  = age;  5 references  string Name  get; set;  5 references  int Age { get; set; }  I reference  void Introduce()  Name =  DefaultName;  DefaultAge;  Age -  Console.WriteLine($"I'm {Name},  {Age} years old. " ) ,

实际上这个不会报错的,出现红色波浪线的原因可能是因为我的Resharper和VS没有升级,Build会成功的。 

 

这里面我做的有点“脱裤子放屁”,但我仅仅是为了展示语言的新特性。 

 

然后在调用的时候,我们可以在IPerson接口上先设置默认值: 

IPerson.SetNameAndAge(  "Nick",  name:  new Teacher();  var teacher =  new Student();  var student =  new Actor()  var actor =  // teacher. Introduce();  38);  age:  C] { teacher,  new IPerson  var persons =  foreach (var person in persons)  person . Introduce( ) ;  student,  actor } ;

 

然后运行: 

I'm Nick, 38 years old.  I'm Nick, 38 years old.  I'm Nick, 38 years old.

可以看到,由于各个实现类都没有自己的实现,所以都输出了默认值。 

 

在类上实现接口方法 

在Teacher类上实现Introduce()这个方法: 

 

然后就可以调用Teacher上的Introduce()方法了: 

 

运行程序: 

可以看到无论是通过Teacher类的实例还是通过IPerson接口,最终调用的都是Teacher类实现的Introduce()方法。 

 

更详细的文档请点击这里查看