在C 8中如何使用預設介面方法詳解

2021-10-20 18:30:30 字數 3146 閱讀 7453

前言

c# 8 中新增了乙個非常有趣的特性,叫做 預設介面方法 (又稱虛擬擴充套件方法),這篇文章將會討論 c# 8 中的預設介面方法以及如何使用。

在 c# 8 之前,介面不能包含方法定義,只能在介面中定義方python基礎教程法簽名,還有乙個就是介面的成員預設是 public 和 abstract , 在 c# 8 之前,介面不能包含字段,也不能包含private, protected, 或者 internal 的方法成員。如果你在介面中引入了乙個新成員,預設情況下你必須更新實現該介面的所有子類。

在 c# 8 中可以在介面定義方法的預設實現,而且還可以定義介面成員為 private,protect,甚至是 static,還有一點挺奇葩的,乙個介面的 protect 成員是不能被實現類所訪問的,相反,它只能在子介面中被訪問,介面的 virtual 成員可以由派生介面 override,但不能被派c#教程生類 override,還有一點請注意,介面目前還不能定義 例項成員。

為什麼要使用預設介面方法

所謂的 預設介面方法 指的是介面中定義了乙個預設實現的方法, 如果實現該介面的類沒有實現預設介面方法的話,那麼這個 預設介面方法 只能從介面上進行訪問,這是乙個很有用的特性,因為它可以幫助開發人員在不破壞現有功能的情況下向介面的未來版本新增新方法。

考慮下面的 ilogger 定義。

public

inte***ce

ilogger

下面的兩個類擴充套件了ilogger介面並實現了log()方法。

public

class

filelogger

:ilogger

}public

class

dblogger

:ilogger

}

現在假設你想在ilogger介面中新增乙個方法,該方法接受兩個引數:乙個 文字 乙個 日誌級別,下面的**片段展示了日誌級別的列舉類。

public

enum loglevel

修改後的 ilogger 介面如下:

public

inte***ce

ilogger

好了,現在問題來了,因為 ilogger 中新增了乙個 log 方法,你必須要在所有實現該介面的所有子類中實現 log(string message, loglevel loglevel) 方法,這就很尷尬了,如果不這樣做的話,編譯器肯定是不會放行的,在現實情況下,這個介面實現類可能在多個 dll 中,甚至在多個團隊中,可想而知,這個工作量是非常大並且非常痛苦的。

預設介面方法案例

這就是 預設介面方法 的應用場景,你可以在介面中定義乙個預設方法是實現,如下**所示:

public

inte***ce

ilogger

}

這個時候,實現 ilogger 介面的子類可以不實現新的 log(string message, loglevel loglevel) 方法,因此下面的**也是跑的通的,編譯器不會丟擲任何錯誤。

public

class

filelogger

:ilogger

}public

class

dblogger

:ilogger

}預設介面方法不能被繼承

現在建立乙個 filelogger 類例項,然後直接呼叫新的帶引數的 log

() 方法,如下**所示:

filelogger filelogger =

newfilelogger()

;filelogger.

log(

"this is a test message."

, loglevel.debug)

;

從上面圖可看出 預設介面方法 不能被子類繼承,換句話說,子類根本就不知道介面中還有帶引數的 log() 方法。

預設介面方法和菱形問題

現在有乙個非常重要的問題,預設介面方法如何避免 菱形問題?換句話說就是 介面的 多繼承 問題,考慮下面的**清單。

public

inte***ce

apublic

inte***ceb:

a}public

inte***cec:

a}public

class

myclass:b

, c

當編譯上面**時,會丟擲乙個編譯錯誤,說 myclass 沒有實現 a.display() 方法,解決這個問題很簡單,在 myclass 中實現一下介面方法就可以了,如下**所示:

public

inte***ce

apublic

inte***ceb:

a}public

inte***cec:

a}public

class

myclass:b

, c}

接下來就可以生成 myclass 例項了,然後再呼叫 display() 方法,如下**所示:

static

void

main

(string

args)

現在問題來了,到底是哪乙個 display() 方法被呼叫了呢?為了避免歧義,c# 將會使用最近覆蓋規則,即 class.display() 方法被最先呼叫。

抽象類 vs 介面

到這裡,我想你肯定有疑問,抽象類 和 介面 是不是很相似了,甚至可以互換了?雖然抽象類和介面現在看起來在很多方面都很相似,但兩者之間還是有微妙的區別的,具體如下:

抽象類可以有例項成員,介面則不能。

抽象類不能多繼承,介面還是可以的。

預設介面方法 允許開發人員利用 trait 程式設計技術,該技術可以讓那些附屬於該方法的不相關型別得以繼續使用,可能你有點懵,我舉個例子:假設你構建好了乙個dll,被很多的開發人員所使用,現在你要發布該 dll 的新版本,比如說往介面中新增了新方法,這個時候你可以定義預設實現,這樣就可以對已使用的開發者進行無感公升級。

您可能感興趣的文章:

c#8.0 中開啟預設介面實現方法

在C 8中如何使用預設介面方法詳解

c 8 中新增了乙個非常有趣的特性,叫做 預設介面方法 又稱虛擬擴充套件方法 這篇文章將會討論 c 8 中的預設介面方法以及如何使用。在 c 8 之前,介面不能包含方法定義,只能在介面中定義方法簽名,還有乙個就是介面的成員預設是 public 和 abstract 在 c 8 之前,介面不能包含字段...

如何在 C 8 中使用預設介面方法

c 8 中新增了乙個非常有趣的特性,叫做預設介面方法 又稱虛擬擴充套件方法 這篇文章將會討論 c 8 中的預設介面方法以及如何使用。在 c 8 之前,介面不能包含方法定義,只能在介面中定義方法簽名,還有乙個就是介面的成員預設是public 和 abstract,在 c 8 之前,介面不能包含字段,也...

微軟在C 8中引入預覽版可空引用型別

微軟已經為開發者提供了預覽版的可空引用型別 nullable reference type 想嘗鮮的開發者可以嘗試這個新特性,並提供反饋。u0026 xd n u0026 xd n 預覽版可空引用型別是visual studio 2017 15.5 preview 4 的roslyn擴充套件,現在支...