介面使用 interface 關鍵字進行定義,如下面的樣本所示:
interface IEquatable<T>
{
bool Equals(T obj);
}
介面描述的是可屬於任何類或結構的一組相關功能。介面可由方法、屬性、事件、索引器或這四種成員類型的任意組合構成。介面不能包含欄位。介面成員一定是公用的。
當類或結構繼承介面時,意味著該類或結構為該介面定義的所有成員提供實現。介面本身不提供類或結構能夠以繼承基類功能的方式繼承的任何功能。但是,如果基類實現介面,衍生類別將繼承該實現。
類和結構可以按照類繼承基類或結構的類似方式繼承介面,但有兩個例外:
類或結構可繼承多個介面。
類或結構繼承介面時,僅繼承方法名稱和簽名,因為介面本身不包含實現。例如:
public class Car : IEquatable<Car>
{
public string Make {get; set;}
public string Model { get; set; }
public string Year { get; set; }
// Implementation of IEquatable<T> interface
public bool Equals(Car car)
{
if (this.Make == car.Make &&
this.Model == car.Model &&
this.Year == car.Year)
{
return true;
}
else
return false;
}
}
若要實現介面成員,類中的對應成員必須是公用的、非靜態,並且與介面成員具有相同的名稱和簽名。類的屬性和索引器可以為介面上定義的屬性或索引器定義額外的訪問器。例如,介面可以聲明一個帶有 get 訪問器的屬性,而實現該介面的類可以聲明同時帶有 get 和 set 訪問器的同一屬性。但是,如果屬性或索引器使用顯式實現,則訪問器必須匹配。
介面和介面成員是抽象的;介面不提供預設實現。有關更多資訊,請參見抽象類別、密封類和類成員。
IEquatable(Of T) 介面向對象的使用者宣布該對象可以確定其是否與同一類型的其他對象相等,而介面的使用者不需要知道相關的實現方式。
介面可以繼承其他介面。類可以通過其繼承的基類或介面多次繼承某個介面。在這種情況下,如果將該介面聲明為新類的一部分,則該類只能實現該介面一次。如果沒有將繼承的介面聲明為新類的一部分,其實現將由聲明它的基類提供。基類可以使用虛擬成員實現介面成員;在這種情況下,繼承介面的類可通過重寫虛擬成員來更改介面行為。有關虛擬成員的更多資訊,請參見多態性。
介面概述
介面具有下列屬性:
本節內容
-
明確介面實作(C# 編程指南)
-
解釋如何建立特定於介面的類成員。
-
如何:顯式實現介面成員(C# 編程指南)
-
提供一個有關如何顯式實現介面成員的樣本。
-
如何:使用繼承顯式實現介面成員(C# 編程指南)
-
提供一個有關如何通過繼承顯式實現介面成員的樣本。
相關章節
-
介面屬性(C# 編程指南)
-
解釋如何聲明介面上的屬性。
-
介面中的索引器(C# 編程指南)
-
解釋如何聲明介面上的索引器。
-
如何:實現介面事件(C# 編程指南)
-
示範介面如何聲明事件。
-
類和結構(C# 編程指南)
-
描述 C# 如何使用對象、類和結構。
顯示介面的實現:
如果類實現兩個介面,並且這兩個介面包含具有相同簽名的成員,那麼在類中實現該成員將導致兩個介面都使用該成員作為它們的實現。例如:
interface IControl
{
void Paint();
}
interface ISurface
{
void Paint();
}
class SampleClass : IControl, ISurface
{
// Both ISurface.Paint and IControl.Paint call this method.
public void Paint()
{
}
}
然而,如果兩個介面成員執行不同的函數,那麼這可能會導致其中一個介面的實現不正確或兩個介面的實現都不正確。可以顯式地實現介面成員 -- 即建立一個僅通過該介面調用並且特定於該介面的類成員。這是使用介面名稱和一個句點命名該類成員來實現的。例如:
public class SampleClass : IControl, ISurface
{
void IControl.Paint()
{
System.Console.WriteLine("IControl.Paint");
}
void ISurface.Paint()
{
System.Console.WriteLine("ISurface.Paint");
}
}
類成員 IControl.Paint 只能通過 IControl 介面使用,ISurface.Paint 只能通過 ISurface 使用。兩個方法實現都是分離的,都不可以直接在類中使用。例如:
SampleClass obj = new SampleClass();
//obj.Paint(); // Compiler error.
IControl c = (IControl)obj;
c.Paint(); // Calls IControl.Paint on SampleClass.
ISurface s = (ISurface)obj;
s.Paint(); // Calls ISurface.Paint on SampleClass.
顯式實現還用於解決兩個介面分別聲明具有相同名稱的不同成員(如屬性和方法)的情況:
interface ILeft
{
int P { get;}
}
interface IRight
{
int P();
}
為了同時實現兩個介面,類必須對屬性 P 和/或方法 P 使用顯式實現以避免編譯器錯誤。例如:
class Middle : ILeft, IRight
{
public int P() { return 0; }
int ILeft.P { get { return 0; } }
}
顯示實現介面成員:
本樣本聲明一個 介面 IDimensions 和一個類 Box,該類顯式實現介面成員 getLength 和 getWidth。通過介面執行個體 dimensions 訪問這些成員。
樣本
interface IDimensions
{
float getLength();
float getWidth();
}
class Box : IDimensions
{
float lengthInches;
float widthInches;
Box(float length, float width)
{
lengthInches = length;
widthInches = width;
}
// Explicit interface member implementation:
float IDimensions.getLength()
{
return lengthInches;
}
// Explicit interface member implementation:
float IDimensions.getWidth()
{
return widthInches;
}
static void Main()
{
// Declare a class instance box1:
Box box1 = new Box(30.0f, 20.0f);
// Declare an interface instance dimensions:
IDimensions dimensions = (IDimensions)box1;
// The following commented lines would produce compilation
// errors because they try to access an explicitly implemented
// interface member from a class instance:
//System.Console.WriteLine("Length: {0}", box1.getlength());
//System.Console.WriteLine("Width: {0}", box1.getwidth());
// Print out the dimensions of the box by calling the methods
// from an instance of the interface:
System.Console.WriteLine("Length: {0}", dimensions.getLength());
System.Console.WriteLine("Width: {0}", dimensions.getWidth());
}
}
/* Output:
Length: 30
Width: 20
*/
可靠編程請注意 Main 方法中下列程式碼被注釋掉,因為它們將產生編譯錯誤。顯式實現的介面成員不能從類執行個體訪問:
//System.Console.WriteLine("Length: {0}", box1.getlength());
//System.Console.WriteLine("Width: {0}", box1.getwidth());還請注意,Main 方法中的下列程式碼成功輸出框的尺寸,因為這些方法是從介面執行個體調用的:
System.Console.WriteLine("Length: {0}", dimensions.getLength());
System.Console.WriteLine("Width: {0}", dimensions.getWidth());