C#8.0默認(rèn)接口實(shí)現(xiàn)的詳細(xì)實(shí)例
Intro
C# 8.0 開(kāi)始引入了默認(rèn)接口實(shí)現(xiàn),也就是可以在接口里寫(xiě)方法實(shí)現(xiàn)。
在之前的版本中接口上是沒(méi)有辦法定義實(shí)現(xiàn)的,方法也都是 public 的,除了接口和屬性之外是不能定義其他數(shù)據(jù)的,這也意味著,接口從一開(kāi)始就要設(shè)計(jì)得比較好,否則在已有接口里增加新方法的時(shí)候其實(shí)現(xiàn)就必須要修改,否則就會(huì)編譯失敗,默認(rèn)接口實(shí)現(xiàn)使得可以不造成破壞性變更的前提下在接口中新增加方法,只需要在接口中提供一個(gè)默認(rèn)的實(shí)現(xiàn)即可。
Sample
下面我們來(lái)看一個(gè)示例吧:
internal interface IFly
{
string Name { get; }
}
internal class Superman : IFly
{
public string Name => nameof(Superman);
}
internal class MonkeyKing : IFly
{
public string Name => nameof(MonkeyKing);
}
這是一個(gè)基本的接口定義,并提供了兩個(gè)實(shí)現(xiàn),緊接著我們來(lái)為接口新增一個(gè)方法,
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");
}
}
我們?cè)诮涌诶镌黾恿艘粋€(gè) Fly 方法,并提供了一個(gè)默認(rèn)實(shí)現(xiàn),在其中一個(gè)實(shí)現(xiàn)中進(jìn)行了重寫(xiě),我們來(lái)寫(xiě)一段代碼測(cè)試一下吧
// Cannot resolve symbol 'Fly' // new Superman().Fly(); IFly fly = new Superman(); fly.Fly(); fly = new MonkeyKing(); fly.Fly();
輸出結(jié)果如下:
Superman is flying
I'm MonkeyKing, I'm flying
IFly
上面的示例中 Superman 沒(méi)有定義 Fly 這個(gè)方法,是不能直接調(diào)用 Fly 方法的,需要先轉(zhuǎn)成 IFly 接口然后再調(diào)用,此時(shí)方法實(shí)現(xiàn)是在接口里定義的邏輯,而 MonkeyKing 實(shí)現(xiàn)了 Fly 方法,所以會(huì)使用它自己的 Fly 實(shí)現(xiàn),如上面所示。
除了上面的基本用法之外,現(xiàn)在可以在接口里定義靜態(tài)字段靜態(tài)方法來(lái)實(shí)現(xiàn)更好的方法復(fù)用,我們?cè)谏厦娴氖纠镅菔疽幌?,修改后的示例如下?/p>
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 的方法或字段,則在實(shí)現(xiàn)接口的類(lèi)中就可以通過(guò) IFly.GetDefaultName() 來(lái)調(diào)用接口中的方法了,如果是 protected 就只能在實(shí)現(xiàn)它的類(lèi)型中使用,如果要在沒(méi)有實(shí)現(xiàn)接口的類(lèi)型中調(diào)用可以聲明為 public 就可以了,下面是在沒(méi)有實(shí)現(xiàn)接口的類(lèi)型中調(diào)用的示例:
// Cannot access protected method 'GetDefaultName' here
// IFly.GetDefaultName().Dump();IFly.GetPublicName().Dump();
More
雖然現(xiàn)在可以這樣用,但我個(gè)人還是推薦沿用之前的接口用法,不要輕易使用這個(gè)特性,提前設(shè)計(jì)提前規(guī)劃才是正道,不要想著事后補(bǔ)償,感覺(jué)這個(gè)特性比較合適的一個(gè)使用場(chǎng)景是現(xiàn)在基于接口的擴(kuò)展方法,擴(kuò)展方法作為一個(gè)接口的默認(rèn)實(shí)現(xiàn),具體類(lèi)可以重寫(xiě)這個(gè)實(shí)現(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);
在之前的版本中,我一般都是把上面的方法作為一個(gè)擴(kuò)展方法來(lái)用,有個(gè)默認(rèn)接口實(shí)現(xiàn)之后也可以考慮加一個(gè)默認(rèn)實(shí)現(xiàn)(僅限于業(yè)務(wù)代碼中,針對(duì)類(lèi)庫(kù)代碼,感覺(jué)還是越干凈越好)
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
總結(jié)
到此這篇關(guān)于C#8.0默認(rèn)接口實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C#8.0默認(rèn)接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Unity?數(shù)據(jù)存儲(chǔ)和讀取的方法匯總
這篇文章主要介紹了Unity?數(shù)據(jù)存儲(chǔ)和讀取的方法,本文通過(guò)四種方法在 Unity 中實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ)和讀取方法的案例內(nèi)容,結(jié)合示例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2022-10-10
WPF實(shí)現(xiàn)帶模糊搜索的DataGrid的示例代碼
這篇文章主要為大家詳細(xì)介紹了WPF如何實(shí)現(xiàn)帶模糊搜索的DataGrid,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下2023-02-02
C#條件拼接Expression<Func<T, bool>>的使用
本文主要介紹了C#條件拼接Expression<Func<T, bool>>的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
淺談C#中的for循環(huán)與foreach循環(huán)
本篇文章主要介紹了C#中的for循環(huán)與foreach循環(huán)的相關(guān)知識(shí),具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-05-05
c# 網(wǎng)址壓縮簡(jiǎn)單實(shí)現(xiàn)短網(wǎng)址
短網(wǎng)址,忽然一下子就冒出來(lái)的東西,長(zhǎng)長(zhǎng)的一個(gè)URL,提交過(guò)去,出來(lái)就只有短短的一個(gè)URL了,看起來(lái)似乎挺神奇,其實(shí)簡(jiǎn)單分析一下,明白其中的原理,也是一件很簡(jiǎn)單的事情,需要的朋友可以了解下2012-12-12

