interface (C# 參考)
介面會定義合約。 任何實作該合約的 class
、record
或 struct
均須提供介面中所定義成員的實作。 介面可以定義成員的預設實作方式。 也可以定義 static
成員,提供通用功能的單一實作。 從 C# 11 開始,介面可能會定義 static abstract
或 static virtual
成員以宣告實作型別必須提供宣告的成員。 通常 static virtual
方法會宣告實作必須定義一組 多載運算子。
在下列範例中,類別 ImplementationClass
必須實作名為 SampleMethod
的方法,該方法沒有參數並會傳回 void
。
如需詳細資訊與範例,請參閱介面。
頂層介面 (在命名空間中宣告,但在另一種型別內不會建立巢狀) 可以宣告為 public
或 internal
。 預設值為 internal
。 巢狀介面宣告 (在另一種型別內宣告的宣告) 可以使用任何存取修飾詞來宣告。
沒有實作的介面成員不能包括存取修飾詞。 具有預設實作的成員可以包括任何存取修飾詞。
範例介面
interface ISampleInterface
{
void SampleMethod();
}
class ImplementationClass : ISampleInterface
{
// Explicit interface member implementation:
void ISampleInterface.SampleMethod()
{
// Method implementation.
}
static void Main()
{
// Declare an interface instance.
ISampleInterface obj = new ImplementationClass();
// Call the member.
obj.SampleMethod();
}
}
介面可以是命名空間或類別的成員。 介面宣告可以包含下列成員的宣告 (不需要任何實作的簽章):
預設介面成員
上述成員宣告通常不包含主體。 介面成員可以宣告主體。 介面中的成員主體預設實作。 具有主體的成員允許介面為未提供覆寫實作的類別和結構提供「預設」實作。
重要
新增預設介面成員會強制實作介面的任何 ref struct
,以新增該成員的明確宣告。
介面可能包括:
- 常數
- 運算子
- 靜態建構函式.
- 巢狀類型
- 靜態欄位、方法、屬性、索引和事件
- 使用明確介面實作語法的成員宣告.
- 明確存取修飾詞 (預設存取為
public
)
靜態抽象和虛擬成員
從 C# 11 開始,介面可以為了除欄位外所有成員型別宣告 static abstract
和 static virtual
成員。 介面可以宣告實作型別必須定義運算子或其他靜態成員。 此功能可讓泛型演算法指定類似數位的行為。 您可以在 .NET 執行階段的數字型別中看到範例,例如 System.Numerics.INumber<TSelf>。 這些介面會定義許多數字型別實作的通用數學運算子。 編譯器必須在編譯時間解析呼叫 static virtual
和 static abstract
方法。 介面中宣告的 static virtual
和 static abstract
方法沒有類似在類別宣告中執行階段分派機制分派的virtual
或 abstract
方法。 而編譯器會使用編譯時間可用的型別資訊。 因此,static virtual
方法幾乎均在泛型介面中完全宣告。 此外,大多數宣告 static virtual
或 static abstract
方法的介面都會宣告其中一個型別參數必須實作宣告的介面。 例如,INumber<T>
介面宣告 T
必須實作 INumber<T>
。 編譯器會使用型別引數解析對介面宣告中所宣告的方法和運算子的呼叫。 例如,int
型別實作 INumber<int>
。 當型別參數 T
代表型別引數 int
時,會叫用在 int
宣告的 static
成員。 或當 double
是型別引數時,會叫用在 double
型別上宣告的 static
成員。
重要
使用運算式的編譯時間型別解析介面中宣告的 static abstract
和 static virtual
方法的方法分派。 如果運算式的執行階段型別衍生自不同的編譯時間型別,則會呼叫基底 (編譯時間上的靜態方法) 型別。
您可以使用介面中靜態抽象成員的教學課程嘗試這項功能。
介面繼承
介面可能不包含執行個體狀態。 雖然現在可使用靜態欄位,但介面中不允許使用執行個體欄位。 介面中不支援執行個體自動屬性,因為其會隱含地宣告隱藏欄位。 此規則對屬性宣告有些微影響。 在介面宣告中,下列程式代碼不會在 或 struct
中class
宣告自動實作的屬性。 相反,它會宣告未預設實作的屬性,但必須在實作介面的任何型別中實作:
public interface INamed
{
public string Name {get; set;}
}
介面可以繼承一或多個基底介面。 當介面繼承自另一個介面時,實作衍生介面的型別必須實作基底介面中的所有成員以及在衍生介面中宣告的成員,如下列程式碼所示:
public interface I1
{
void M1();
}
public interface I2 : I1
{
void M2();
}
public class C : I2
{
// implements I1.M1
public void M1() { }
// implements I2.M2
public void M2() { }
}
當介面 覆寫基底介面中實作的 方法時,它必須使用明確介面實作語法。
當基底類型清單包含基底類別和介面時,基底類別一定會排在清單的第一個。
實作介面的類別能夠明確實作該介面的成員。 明確實作的成員不能經由類別執行個體存取,只能經由介面的執行個體來存取。 此外,預設介面成員只能透過介面的執行個體存取。
如需明確介面實作的詳細資訊,請參閱明確介面實作。
介面實作範例
下列範例示範介面實作。 在此範例中,介面包含屬性宣告,而類別包含實作。 實作 IPoint
的任何類別執行個體都有整數屬性 x
和 y
。
interface IPoint
{
// Property signatures:
int X { get; set; }
int Y { get; set; }
double Distance { get; }
}
class Point : IPoint
{
// Constructor:
public Point(int x, int y)
{
X = x;
Y = y;
}
// Property implementation:
public int X { get; set; }
public int Y { get; set; }
// Property implementation
public double Distance =>
Math.Sqrt(X * X + Y * Y);
}
class MainClass
{
static void PrintPoint(IPoint p)
{
Console.WriteLine("x={0}, y={1}", p.X, p.Y);
}
static void Main()
{
IPoint p = new Point(2, 3);
Console.Write("My Point: ");
PrintPoint(p);
}
}
// Output: My Point: x=2, y=3
C# 語言規格
如需詳細資訊,請參閱 C# 語言規格的介面一節,C# 8:預設介面成員的功能規格,和 C# 11:介面中的靜態抽象成員的功能規格