C#8.0默認接口實現(xiàn)的詳細實例
Intro
C# 8.0 開始引入了默認接口實現(xiàn),也就是可以在接口里寫方法實現(xiàn)。
在之前的版本中接口上是沒有辦法定義實現(xiàn)的,方法也都是 public 的,除了接口和屬性之外是不能定義其他數(shù)據(jù)的,這也意味著,接口從一開始就要設計得比較好,否則在已有接口里增加新方法的時候其實現(xiàn)就必須要修改,否則就會編譯失敗,默認接口實現(xiàn)使得可以不造成破壞性變更的前提下在接口中新增加方法,只需要在接口中提供一個默認的實現(xiàn)即可。
Sample
下面我們來看一個示例吧:
internal interface IFly { string Name { get; } } internal class Superman : IFly { public string Name => nameof(Superman); } internal class MonkeyKing : IFly { public string Name => nameof(MonkeyKing); }
這是一個基本的接口定義,并提供了兩個實現(xiàn),緊接著我們來為接口新增一個方法,
internal interface IFly { string Name { get; } void Fly() => Console.WriteLine($"{Name.GetValueOrDefault((DefaultName))} is flying"); } internal class Superman : IFly { public string Name => nameof(Superman); public void Test() { ((IFly) this).Fly(); Console.WriteLine(Name); } } internal class MonkeyKing : IFly { public string Name => nameof(MonkeyKing); public void Fly() { Console.WriteLine($"I'm {Name}, I'm flying"); } }
我們在接口里增加了一個 Fly 方法,并提供了一個默認實現(xiàn),在其中一個實現(xiàn)中進行了重寫,我們來寫一段代碼測試一下吧
// Cannot resolve symbol 'Fly' // new Superman().Fly(); IFly fly = new Superman(); fly.Fly(); fly = new MonkeyKing(); fly.Fly();
輸出結果如下:
Superman is flying
I'm MonkeyKing, I'm flying
IFly
上面的示例中 Superman 沒有定義 Fly 這個方法,是不能直接調(diào)用 Fly 方法的,需要先轉成 IFly 接口然后再調(diào)用,此時方法實現(xiàn)是在接口里定義的邏輯,而 MonkeyKing 實現(xiàn)了 Fly 方法,所以會使用它自己的 Fly 實現(xiàn),如上面所示。
除了上面的基本用法之外,現(xiàn)在可以在接口里定義靜態(tài)字段靜態(tài)方法來實現(xiàn)更好的方法復用,我們在上面的示例里演示一下,修改后的示例如下:
internal interface IFly { private const string DefaultName = nameof(IFly); protected static string GetDefaultName() => DefaultName; public static string GetPublicName() => DefaultName; // Interface cannot contain instance fields // private string name = ""; string Name { get; } void Fly() => Console.WriteLine($"{Name.GetValueOrDefault((DefaultName))} is flying"); } internal class MonkeyKing : IFly { public string Name => nameof(MonkeyKing); public void Fly() { Console.WriteLine($"I'm {Name}, I'm flying, DefaultName:{IFly.GetDefaultName()}"); } }
如果定義了 protected static 的方法或字段,則在實現(xiàn)接口的類中就可以通過 IFly.GetDefaultName() 來調(diào)用接口中的方法了,如果是 protected 就只能在實現(xiàn)它的類型中使用,如果要在沒有實現(xiàn)接口的類型中調(diào)用可以聲明為 public 就可以了,下面是在沒有實現(xiàn)接口的類型中調(diào)用的示例:
// Cannot access protected method 'GetDefaultName' here
// IFly.GetDefaultName().Dump();IFly.GetPublicName().Dump();
More
雖然現(xiàn)在可以這樣用,但我個人還是推薦沿用之前的接口用法,不要輕易使用這個特性,提前設計提前規(guī)劃才是正道,不要想著事后補償,感覺這個特性比較合適的一個使用場景是現(xiàn)在基于接口的擴展方法,擴展方法作為一個接口的默認實現(xiàn),具體類可以重寫這個實現(xiàn),使用示例如下:
Task<bool> SaveProperties(int id, Dictionary<string, object> properties) { if (properties is null || properties.Count == 0) return Task.FromResult(false); var json = JsonConvert.SerializeObject(properties.Select(p => new PropertyModel() { PropertyName = p.Key, PropertyValue = p.Value?.ToString() })); return SaveProperties(id, json); } Task<bool> SaveProperties(int id, string properties);
在之前的版本中,我一般都是把上面的方法作為一個擴展方法來用,有個默認接口實現(xiàn)之后也可以考慮加一個默認實現(xiàn)(僅限于業(yè)務代碼中,針對類庫代碼,感覺還是越干凈越好)
References
- https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/default-interface-methods-versions
- https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#default-interface-methods
- https://github.com/WeihanLi/SamplesInPractice/blob/master/CSharp9Sample/DefaultInterfaceImplement.cs
總結
到此這篇關于C#8.0默認接口實現(xiàn)的文章就介紹到這了,更多相關C#8.0默認接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C#實現(xiàn)HTML轉WORD及WORD轉PDF的方法
這篇文章主要介紹了C#實現(xiàn)HTML轉WORD及WORD轉PDF的方法,涉及C#實現(xiàn)HTML、WORD及PDF等文件格式轉換的相關技巧,需要的朋友可以參考下2015-09-09C#中BitConverter.ToUInt16()和BitConverter.ToString()的簡單使用
這篇文章主要介紹了C#中BitConverter.ToUInt16()和BitConverter.ToString()的簡單使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-02-02C#將PDF轉為多種圖像文件格式的方法(Png/Bmp/Emf/Tiff)
這里介紹將PDF轉換多種不同格式的圖像文件格式,如PNG,BMP,EMF,TIFF等,同時,轉換文檔也分為轉換全部文檔和轉換部分文檔為圖片兩種情況,本文也將作進一步介紹2018-02-02