ZetCode

C# 扩展方法

最后修改于 2024 年 7 月 7 日

在本文中,我们将展示如何在 C# 中定义和使用扩展方法。

C# 扩展方法

扩展方法是可以插入到现有类型中的方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。

扩展方法是静态方法,但在 C# 中,它们的调用方式就像普通的 C# 方法一样。它们在其参数中使用 this 修饰符。

只有当我们使用 using 指令将命名空间显式导入到源代码中时,扩展方法才在作用域内。

在标准库中,我们可以找到大量的扩展方法,最值得注意的是 LINQ。

C# LINQ 扩展方法

LINQ 是一种内置于 C# 中的小型语言,它带来了更高级的查询能力。

Program.cs
string[] words = [ "falcon", "oak", "sky", "cloud", "tree", "tea", "water" ];

Console.WriteLine(words.First(word => word.Length == 3));
Console.WriteLine(words.Last(word => word.Length == 3));

该示例打印了第一个和最后一个具有三个字母的单词。

Console.WriteLine(words.First(word => word.Length == 3));
Console.WriteLine(words.Last(word => word.Length == 3));

FirstLast 都是 C# 扩展方法,它们定义在 System.Linq 命名空间中。

$ dotnet run
oak
tea

C# 扩展方法示例

在以下示例中,我们向 string 类型添加一个新方法。

Program.cs
var msg = "We walked for hours. We saw four hawks in the sky.";

int n = msg.WordCount();
Console.WriteLine(n);

public static class ExtensionMethods
{
    public static int WordCount(this string str)
    {
        return str.Split(new char[] { ' ', '.', '?' },
            StringSplitOptions.RemoveEmptyEntries).Length;
    }
}

WordCount 方法是静态类中定义的静态方法。它的参数包含 this 关键字。

int n = msg.WordCount();

该方法直接在字符串上调用。

$ dotnet run
11

C# 扩展方法示例 II

在下一个示例中,我们向 int 类型添加一个扩展方法。

Program.cs
int x = 20;
int y = -5;

Console.WriteLine(x.Abs());
Console.WriteLine(y.Abs());

public static class ExtensionMethods
{
    public static int Abs(this int val)
    {
        if (val < 0)
        {
            return -val;
        }

        return val;
    }
}

该示例添加了 Abs 方法,该方法返回给定整数的绝对值。

$ dotnet run
20
5

C# 泛型扩展方法

在下一个示例中,我们为列表类型定义一个 FindAll 扩展方法。

ExtensionMethods.cs
public static class ExtensionMethods
{
    public static List<T> FindAll<T>(this List<T> vals, List<Predicate<T>> preds)
    {
        List<T> data = new List<T>();

        foreach (T e in vals)
        {
            bool pass = true;

            foreach (Predicate<T> p in preds)
            {
                if (!(p(e)))
                {
                    pass = false;
                    break;
                }
            }

            if (pass) data.Add(e);
        }

        return data;
    }
}

FindAll 方法返回满足所有指定谓词的列表元素。

public static List<T> FindAll<T>(this List<T> vals, List<Predicate<T>> preds)

FindAll 方法将泛型谓词函数列表作为参数。 它返回一个经过过滤的泛型列表。

Program.cs
List<Predicate<int>> preds = [e => e > 0, e => e % 2 == 0];

List<int> vals = [-3, -2, -1, 0, 1, 2, 3, 4];
var filtered = vals.FindAll(preds);

foreach (var e in filtered)
{

    Console.WriteLine(e);
}

Console.WriteLine("---------------------");

List<string> words = ["sky", "wrath", "wet", "sun", "pick", "who",
    "cloud", "war", "water", "jump", "ocean"];

List<Predicate<string>> preds2 = [e => e.StartsWith("w"), e => e.Length == 3];

var filtered2 = words.FindAll(preds2);

foreach (var e in filtered2)
{

    Console.WriteLine(e);
}

我们定义两个列表:一个整数列表和一个字符串列表。 从整数列表中,我们过滤掉所有正偶数值。 从字符串列表中,我们获取所有以“w”开头且包含三个字母的单词。

$ dotnet run
2
4
---------------------
wet
who
war

C# Base64 扩展方法

在以下示例中,我们创建用于编码和解码 Base64 数据的扩展方法。Base64 是一组类似的二进制到文本编码方案,用于以文本字符串格式表示二进制数据。

Program.cs
using System.Text;

namespace Base64Ex;

class Program
{
    static void Main()
    {
        string msg = "one 🐘 and three 🐋";
        string base64 = msg.EncodeBase64();
        string msg2 = base64.DecodeBase64();

        Console.WriteLine(msg);
        Console.WriteLine(base64);
        Console.WriteLine(msg2);
    }
}

static class ExtensionMethods
{
    public static string EncodeBase64(this string value)
    {
        byte[] data = Encoding.UTF8.GetBytes(value);
        return Convert.ToBase64String(data);
    }

    public static string DecodeBase64(this string value)
    {
        byte[] data = System.Convert.FromBase64String(value);
        return Encoding.UTF8.GetString(data);
    }
}

该程序创建了 EncodeBase64DecodeBase64 扩展方法。

string msg = "one 🐘 and three 🐋";
string base64 = msg.EncodeBase64();
string msg2 = base64.DecodeBase64();

扩展方法可以直接在字符串上调用。

$ dotnet run
one 🐘 and three 🐋
b25lIPCfkJggYW5kIHRocmVlIPCfkIs=
one 🐘 and three 🐋

来源

扩展方法

在本文中,我们研究了 C# 中的扩展方法。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直在撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程