使用 C# 中的扩展方法构建流畅的代码

2025-06-07

使用 C# 中的扩展方法构建流畅的代码

扩展方法是现代 .NET 不可或缺的一部分,也是 .NET 一些优秀功能(例如 LINQ)的一部分。然而,许多开发人员对扩展方法望而却步,不了解其底层机制,也不知道如何构建新的扩展方法。在本文中,我将尝试揭开扩展方法的神秘面纱,并演示如何使用它们构建优雅流畅的代码。

基础知识:静态方法

为了讨论扩展方法,我们必须首先讨论静态方法。

静态方法只是用static关键字声明的方法。这告诉 .NET 该方法不是基于特定实例运行,而是附加到整个类中。由于这些方法是静态的,因此它们无法访问任何特定实例的状态,除非将其作为参数传递给方法(稍后会详细介绍)。

Integer.Parse方法是一种相当著名的静态方法String.IsNullOrEmpty

在本文中,我们将构建一种获取书籍信息的方法,因此让我们创建一个构建书籍列表的静态方法。

现在,为了获取我们的书籍,我们只需执行以下操作:

var books = Books.GetBooks();

使用起来非常简单。

扩展方法

接下来让我们将注意力转向扩展方法。

简而言之,扩展方法是特殊声明的静态方法,编译器允许您在与其签名匹配的对象上调用这些方法。

让我告诉你我的意思。

假设我们有以下静态方法:

在这里我们可以获取任何Book实例并将其传递给Books.IsBoring并获得布尔响应。

让我们将其改为扩展方法。

由于扩展方法只能在静态类(无法实例化且只有静态成员的类)中声明,因此我们需要static在类中添加关键字。

现在,我们通过将关键字添加到第一个参数来将我们的IsBoring方法声明为扩展方法,如下所示:this

this关键字告诉 .NET 这是IsBoring一种扩展方法,可以通过类似的静态方法语法Books.IsBoring(someBook)或类似的扩展方法语法进行调用someBook.IsBoring()

注意,this扩展方法语法中的关键字只能用于第一个参数,即该方法扩展的类型或接口。

扩展方法是语法糖,可以让编译器将扩​​展方法样式调用替换为静态方法调用。

然而,最终结果是,扩展方法让你看起来像是把新功能添加到了其他类或接口上。这是它们的主要优势,因为扩展方法允许你简化调用语法,但代价是让普通读者难以理解方法的确切声明位置。

现在我们知道了什么是扩展方法,让我们看看如何使用它们来构建流畅的语法或特定领域的语言。

将扩展方法链接在一起

假设您要创建一本书,并且需要执行一系列操作才能创建一本有效的书。如果您想提供一个相当灵活且可读的 API,可以使用扩展方法来创建一个微型领域特定语言 (DSL)。

在这个例子中,我们的最终目标是创建一个根据我们配置的值定制的书籍对象。

让我们首先关注最终结果:

那里发生了很多事情,但可能没有你想象的那么多。

让我们从Books.CreateBook调用开始。这是一个静态方法调用,它接受一个表示书名的字符串作为参数,并返回一个神秘的对象。

我们将该对象称为 aBookBuilder并假设它看起来像这样:

好的,现在这可能更有意义了。这意味着我们的CreateBook静态方法应该如下所示:

接下来,我们的示例中调用了WrittenBy。嗯,这个BookBuilder类并没有定义该方法。在普通的应用程序中,我们可能只会将该方法添加到BookBuilder,但这不允许我们在这里使用扩展方法,所以让我们假装这个BookBuilder类是由一些我们无法控制且无法修改的代码定义的。

我们将WrittenBy通过添加扩展方法来处理该方法:

这是一个非常简单的方法,但这里有一些关键的事情。

BookBuilder首先,由于this参数签名中的关键字,该方法充当实例上的扩展方法。

其次,该方法仅使用指定的一个参数进行调用(例如WrittenBy("Michael Crichton"),因为第一个参数是根据BookBuilder您调用扩展方法推断出来的。

第三,我们返回与之前返回的相同的构建器实例。返回此参数完全是为了支持流畅的语法(就像我们在前面的示例中看到的那样),并允许在先前扩展方法的返回结果上调用扩展方法。

最终的静态类可能看起来像这样:

这可能看起来不是您见过的最漂亮的代码,但它可以创建的语法类型却非常强大和美观。

让我们谈谈 LINQ

为了支持.NET Framework 3.5 中的语言集成查询( LINQ ) ,扩展方法被明确添加到 C# 语言中

就开发人员生产力而言,LINQ 是我最喜欢的 C# 功能之一,如果没有扩展方法,这一切都不可能实现。

LINQ 可以让你执行以下操作:

也许这是一个有点傻的例子,但这一切都是通过使用扩展方法来接受IEnumerable<T>IQueryable<T>使用各种Func签名来过滤、排序或转换集合来实现的。

换句话说,如果你真的想,你可以使用扩展方法,用几乎完全相同的语法编写自己的 LINQ 版本。请不要这样做——微软已经做得很好了——但扩展方法的功能允许你这样做。

结束语

希望这可以揭开扩展方法、LINQ 和静态与实例方法背后的一些魔力。

我确信扩展方法(以及 LINQ 扩展)是 .NET 技术提高生产力的关键因素之一,与基类库、公共语言运行时、Visual Studio 和泛型等并列。

虽然您可能不会创建甚至不会考虑扩展方法,但它们为我们在现代 .NET 中所做的很多工作提供支持,并且它们提供的灵活性可以成为一种很好的工具。

使用 C# 中的扩展方法构建流畅代码一文首先出现在Kill All Defects上。

文章来源:https://dev.to/integerman/using-extension-methods-in-c-to-build- Fluent-code-4b49
PREV
样式位置以更好的方式固定
NEXT
我犯过的最严重的错误