C# 中委托和接口的区别

2025年3月17日 | 阅读 10 分钟

在本文中,您将了解 C# 中**委托**和**接口**之间的区别。但在讨论区别之前,您必须了解 C# 中的委托和接口及其语法和示例。

C# 中委托的介绍

在 C# 中,**委托**是一种表示对具有特定签名的方法的引用的类型。它允许将方法视为可以分配给变量、作为参数传递给其他方法以及动态调用的实体。委托提供了一种实现回调函数的方式,您可以将方法作为参数传递给另一个方法,并让该方法调用接受的方法。

Difference between delegates and interfaces in C#

以下是 C# 委托的基本介绍

它声明了一个名为 **Delegate** 的委托,它可以引用接受整数参数并返回空值的方法。您可以根据要引用的方法自定义委托签名。

建立一个代表

这是与委托签名匹配的 **"SomeMethod"** 方法。现在,委托引用此方法。

调用委托

它调用委托引用的方法,并传递整数值 10。

使用委托进行多播

委托可以引用多个方法,从而实现多播

现在,当您调用 **myDelegate** 时,它将按照添加的顺序调用 **"SomeMethod"**、**"AnotherMethod"** 和 **"YetAnotherMethod"**。

委托的用例

C# 中有几个**委托**的用例。委托的一些主要用例如下

1. 回调机制

委托通常用于实现回调机制,其中方法将操作的一部分委托给调用方提供的方法。

2. 事件处理

委托在 C# 事件处理中广泛使用。事件基于委托,是一种在特定操作发生时通知的方式。

3. 异步编程

委托用于异步编程以异步调用方法,特别是 **BeginInvoke** 和 **EndInvoke** 方法。

4. LINQ

委托在 LINQ 查询中用于谓词函数或在排序操作中定义键选择器。委托通过允许将方法视为一流公民,在 C# 代码中实现灵活性和解耦方面发挥着重要作用。它们是语言不可或缺的一部分,并支持函数式编程概念。

委托的程序

让我们举一个例子来说明 C# 中的**委托**。

输出

运行此程序时,您应该看到以下输出

PrintNumber: 42
PrintNumber: 10
DoubleNumber: 20

说明

在此示例中,**MyDelegate** 被声明为可以引用接受整数参数并返回 null 的方法的委托。方法 **"PrintNumber"** 和 **"DoubleNumber"** 对应于委托签名。创建“Delegate”实例并为其分配“PrintNumber”方法。

使用整数**“argument”**调用委托。使用 += 语法将另一个方法 (DoubleNumber) 添加到委托。再次调用委托,这次调用两个方法(PrintNumber 和 DoubleNumber)。

C# 中接口的介绍

**接口声明:**C# **接口**是一种引用类型,它定义类的实现契约。它充当蓝图,定义一组方法签名、属性签名、事件和索引器,而不提供实现。

语法

它具有以下语法:

主要特点

C# 中接口有几个主要特性。接口的一些主要特性如下

**抽象:**接口通过定义实现类必须遵循的通用约定来提供抽象级别。

**方法签名:**接口包含方法签名,但不指定这些方法应该如何实现。

**属性、事件和索引器:**除了方法之外,接口还可以声明实现类必须定义的属性、事件和索引器。

**实现多个接口:**C# 类可以实现多个接口,从而允许它同时遵循多个约定。

**类 MyDerivedClass:**IExampleInterface、IAnotherInterface。

用例

接口有几个用例。接口的一些主要用例如下

**多态性:**接口通过允许不同类的对象由接口类型统一处理来实现多态性。

**依赖注入:**接口通常用于依赖注入场景,促进代码架构中的松散耦合和灵活性。

**API 设计:**接口在 API 设计中很有价值,因为它们为特定库或模块的用户提供了清晰的契约。

C# 中接口的程序

让我们举一个例子来说明 C# 中的**接口**。

输出

运行此程序时,您应该看到以下输出

Circle Area: 78.54
Rectangle Area: 24.00

说明

在此程序中,我们定义了具有一个 **"CalculateArea"** 方法的 **"IShape"** 接口。

两个类 Circle 和 Rectangle 实现 "IShape" 接口,提供其 "CalculateArea" 方法的实现。在 Main 方法中,我们创建这两个类的实例并将它们视为 "IShape" 对象。之后,我们为每个形状调用 "CalculateArea" 方法,并根据对象的实际类型调用适当的实现。

C# 中委托和接口的区别

委托和接口都是 C# 中重要的概念,它们促进了编程的各个方面。以下是委托和接口之间的主要区别

目的

**委托:**委托用于创建对方法的引用并通过委托对象调用这些方法。它们主要用于实现回调机制、事件处理和观察者设计模式。

**接口:**接口定义类中实现的契约。它们用于声明类必须提供的一组方法、属性、事件或索引器。接口用于实现抽象并在类之间实现通用结构。

契约类型

**委托:**委托允许您创建对具有特定签名的方法的引用。它们更侧重于方法签名和函数指针。

**接口:**接口定义类必须遵循的约定。它包含实现类必须提供的一组方法签名、属性、事件或索引器。

方法数量

**委托:**委托可以表示单个方法或具有相同签名的方法链(多播委托)。

**接口:**接口可以声明必须由实现接口的类提供的多个方法、属性、事件或索引器。

实施

**委托:**委托由 delegate 关键字实现,并通过与委托签名匹配的方法或方法集实例化。

**接口:**接口使用 interface 关键字实现。一个类可以实现一个或多个接口,为接口的每个成员提供特定的实现。

灵活性

**委托:**委托在运行时动态定义方法和创建事件处理机制方面提供更大的灵活性。

**接口:**接口提供更结构化的方法,通常用于当一组类必须遵循一组公共方法时。

事件处理

**委托:**委托通常用于处理 C# 中的事件,允许多个方法订阅事件。

**接口:**虽然接口本身不直接用于处理事务,但它们可以与事务关联以定义事务订阅者的契约。

继承

**委托:**委托不支持继承。每个委托类型都是独立的,不能从其他委托类型派生或继承。

**接口:**接口支持继承。一个类可以实现多个接口,接口本身可以从其他接口继承,从而形成层次结构。

可空性

**委托:**委托可以为空,这意味着它们不一定必须引用方法。此属性通常用于在调用委托之前检查委托是否已订阅方法。

**接口:**接口实例不能为空,因为它们由类实现。但是,如果接口类型的引用变量未分配给实现该接口的类的实例,则它们可以为空。

编译时与运行时绑定

**委托:**委托提供动态或运行时绑定。要调用的实际方法在委托调用时在运行时确定。

**接口:**接口方法在编译时绑定。编译器确保实现接口的类为接口的所有成员提供具体实现。

多种方法签名

**委托:**单个委托类型可以表示具有不同签名的方法,只要它们与委托的返回类型和参数类型匹配即可。

**接口:**接口上的每个方法都必须在该接口上具有唯一的签名,这鼓励严格定义方法契约。

性能

**委托:**委托可能在创建和调用委托对象方面有点负担,特别是对于多角色委托。

**接口:**接口方法调用可以具有更好的性能,因为它们在编译时解析,并且不会产生与委托相关的开销。

匿名方法和 Lambda

**委托:**委托可以轻松地与匿名方法和 lambda 表达式一起使用,提供简洁的方式来内联定义方法实现。

**接口:**虽然接口本身不支持匿名方法或 lambda,但实现接口的类可以使用这些功能来实现接口成员。

结论

**委托**和**接口**是 C# 的基本概念,在塑造面向对象应用程序的设计和功能方面发挥着特殊作用。了解这两种结构之间的关键区别对于希望有效利用其技能的开发人员非常重要。

委托主要作为函数指针,提供了一种创建方法引用的机制。它们的主要目的是实现方法的动态调用,从而允许实现回调机制和支持事件处理等场景。使用 delegate 关键字声明的委托允许方法被封装并作为参数传递,存储在数据结构中,或在运行时动态调用。这种灵活性使委托在只有在运行时才知道确切执行方法的场景中很有用。它们通过允许多个方法附加到给定事件并通过多播委托调用,显着推进了事件驱动编程范式。

另一方面,**接口**侧重于通过定义一组方法签名、属性、事件或索引器来定义类必须遵循的约定。 interface 关键字用于声明接口,并且需要实现类来为接口中定义的所有成员提供特定的实现。接口通过允许类实现多个接口,在 C# 中实现多重继承方面发挥着关键作用。它促进了代码重用并确保了类之间的一致结构,使接口成为面向对象编程范式中的关键元素。

委托和接口之间最重要的区别之一是它们的继承实现。委托不支持多重继承,将类继承限制在一个委托中。另一方面,接口非常适合提供多重继承解决方案,允许类实现多个接口。这种区别突出了接口在创建更模块化和可扩展的代码库中的作用,因为类可以从多个源继承行为,而没有单一继承的限制。

事件处理是委托擅长的领域,因为它们通常用于实现 C# 编程的这一重要部分。C# 中的事件本质上是多播委托,允许多个方法附加到事件。在这种情况下,委托作为封装响应事件发生的方法的一种手段,提供了一种干净有效的方式来实现观察者模型。虽然接口本身不直接处理事件,但它们通常与模式(例如 EventSubscriber 模式)结合使用,以定义打算订阅事件的类的契约。

为了灵活性和可用性,委托在需要动态方法调用的场景中特别有价值,例如异步编程或调用方法可能在运行时更改的情况。它们动态封装和调用方法的能力使其适用于在编译时不知道确切方法的场景。另一方面,接口提供了一种更结构化和静态定义的方法来实现类之间的共享功能。它们通过强制实现类的标准化约定来促进代码一致性、可重用性和可维护性。

总之,虽然**委托**和**接口**都对 C# 编程环境做出了重大贡献,但它们的作用和应用却大相径庭。委托在需要动态方法调用和事件处理的场景中表现出色,为方法引用和执行提供了灵活的机制。另一方面,接口侧重于定义类契约,促进代码重用和促进多重继承。委托和接口之间的选择取决于应用程序的具体要求,仔细考虑它们的优缺点对于 C# 中的有效软件设计至关重要。