接口定义协定。实现该协定的任何 class、record 或 struct 必须提供接口中定义的成员的实现。接口可为成员定义默认实现。它还可以定义 static 成员,以便提供常见功能的单个实现。 从 C# 11 开始,接口可以定义 static abstract 或 static virtual 成员来声明实现类型必须提供声明的成员。通常,static virtual 方法声明实现必须定义一组重载运算符。
在以下示例中,类“Lei示例接口”必须实现一个不含参数但返回 void 的名为 i示例接口 . FF 的方法。
顶级接口(在命名空间中声明但未嵌套在另一种类型的接口中)可以声明为 public 或 internal。 默认为 internal。 嵌套接口声明(在另一类型内部声明的接口)可以使用任何访问修饰符声明。
没有实现的接口成员不能包含访问修饰符。 具有默认实现的成员可以包含任何访问修饰符。
static void Main(string[] args)
{
i示例接口 dx = new Lei实现接口 ( );
dx . FF示例 ( );
}
interface i示例接口
{
void FF示例 ( );
}
class Lei实现接口 : i示例接口
{
void i示例接口 . FF示例 ( )
{
Console . WriteLine ( $"实现了接口。" );
}
}
接口可以是命名空间或类的成员。 接口声明可以包含以下成员的声明(没有任何实现的签名):
- 方法
- 属性
- 索引器
- 事件
默认接口成员
上述成员声明通常不包含主体。接口成员可以声明主体。接口中的成员主体是默认实现。具有主体的成员允许接口为不提供重写实现的类和结构提供“默认”实现。
重要:添加默认接口成员会强制实现接口的任何 ref struct 添加该成员的显式声明。
接口可能包括:
- 常量
- 运算符
- static 构造函数。
- 嵌套类型
- static 字段、方法、属性、索引和事件
- 使用显式接口实现语法的成员声明
- 显式访问修饰符(默认访问权限为 public)
静态抽象成员和虚拟成员
从 C# 11 开始,接口可以声明除字段之外的所有成员类型的 static abstract 和 static virtual 成员。接口可以声明实现类型必须定义运算符或其他 static 成员。此功能使泛型算法能够指定类似于数字的行为。可以在 .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 时,将调用 static 上声明的 int 成员。或者,当 double 是类型参数时,将调用在 static 类型上声明的 double 成员。
重要:使用表达式的编译时类型解析接口中声明的 static abstract 和 static virtual 方法的方法调度。如果表达式的运行时类型派生自不同的编译时类型,将调用基(编译时)类型的 static 方法。
可以通过使用有关接口中静态抽象成员的教程来尝试此功能。
接口继承
接口不能包含实例状态。虽然现在允许使用 static 字段,但接口中不允许使用实例字段。接口中不支持实例自动属性,因为它们将隐式声明隐藏的字段。此规则对属性声明有细微影响。在接口声明中,以下代码不会像在接口 class 声明中那样声明自动实现的属性 struct。相反,它会声明一个属性,该属性没有默认实现,而必须在该实现接口的任何类型中实现它:
interface i示例接口
{
public string Ming
{
get;
set;
}
}
class Lei实现接口 : i示例接口
{
private string ming = "我自己";
public string Ming
{
get => ming;
set => ming = value;
}
static void Main(string[] args)
{
i示例接口 dx = new Lei实现接口 ( );
dx . Ming = "wzj";
Console . WriteLine ( dx .Ming );
}
一个接口可从一个或多个基接口继承。当接口继承自另一个接口时,实现派生接口的类型必须实现基接口中的所有成员以及派生接口中声明的成员,如以下代码所示:
public interface iJi
{
void FFJi ( );
}
public interface iP
{
void FFP ( );
}
public class LeiIP : iJi , iP
{
// 实现 iJi 的 FFJi
public void FFJi ( ) => Console . WriteLine ( "实现了 iJi 的 FFJi。" );
// 实现 iP 的 FFP
public void FFP ( ) => Console . WriteLine ( "实现了 iP 的 FFP。" );
}
static void Main(string[] args)
{
iJi ji = new LeiIP ( );
ji . FFJi ( );
iP dx = new LeiIP ( );
dx . FFP ( );
}
当接口重写基接口中的方法实现时,必须使用显式接口实现语法。
基类型列表包含基类和接口时,基类必须是列表中的第 1 项。
实现接口的类可以显式实现该接口的成员。显式实现的成员不能通过类实例访问,而只能通过接口实例访问。此外,只能通过接口实例访问默认接口成员。
接口实现示例
下例演示了接口实现。在此示例中,接口包含属性声明,类包含实现。实现 IDian 的类的任何实例都具有整数属性 x 和 y。
public interface iDian
{
// 属性点值
int x
{
get;
set;
}
int y
{
get;
set;
}
double 距离
{
get;
}
}
public class Dian : iDian
{
// 构造器:
public Dian ( int x , int y )
{
this . x = x;
this . y = y;
}
// 结构:
public int x
{
get;
set;
}
public int y
{
get;
set;
}
// 与原点的距离
public double 距离 => Math . Sqrt ( x * x + y * y );
}
static void Main(string[] args)
{
Dian d = new ( 2 , 3 );
Console . Write ( $"点:" );
FF输出点 ( d );
Console . WriteLine($"与原点的距离:{d . 距离}" );
}
static void FF输出点 ( iDian 点 )
{
iDian id = 点;
Console . WriteLine ( $"{点 . x},{点 . y}" );
}
输出:
点:2,3
3.605551275463989
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。