C#——扩展方法

扩展方法

定义

扩展方法(Extension Methods)是C#中一种特殊的静态方法,它定义在一个静态类中,但是可以像实例方法一样被调用,使得代码更加简洁、易读。

设计目的

是为了给已有的类型添加新的行为,而不需要修改这些类型的原始定义。

特点

扩展方法有以下特点:

  1. 它必须在一个静态类中定义。
  2. 它必须有至少一个参数。
  3. 第一个参数必须有this前缀,并且指定了要扩展的类型。
  4. 第一个参数不能有任何其他的修饰符(如out或ref)。

示例一:

下面是一个扩展方法的示例,这个方法会在string类型上添加一个新的扩展方法,实现将字符串转换为全部大写的功能:

定义扩展方法

public static class ExtensionMethods
{
    public static string ToUpperCase(this string str)
    {
        return str.ToUpper();
    }
}

使用扩展方法

string original = "Hello, World!";
string upperCase = original.ToUpperCase();
Console.WriteLine(upperCase);  // 输出 "HELLO, WORLD!"
Console.WriteLine("aaaa".ToUpperCase()); 

实际上,编译后,扩展方法调用就会翻译成普通的静态方法调用了

Console.WriteLine(ExtensionMethods.ToUpperCase("aaaa")); 

示例二:

需要一个扩展方法来帮助我们计算字符串中某个子串出现的次数,并且还可以指定是否忽略大小写。

定义扩展方法

using System;
using System.Collections.Generic;
using System.Linq;

public static class StringExtensions
{
    // 扩展方法,用于计算字符串中子串出现的次数
    public static int CountOccurrences(this string source, string toFind, bool ignoreCase = false)
    {
        if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(toFind))
            return 0;

        if (ignoreCase)
        {
            source = source.ToLower();
            toFind = toFind.ToLower();
        }

        int count = 0;
        int start = 0;
        while ((start = source.IndexOf(toFind, start)) != -1)
        {
            count++;
            start += toFind.Length;
        }

        return count;
    }
}

在这个例子中,CountOccurrences 方法的第一个参数 source 是带有 this 关键字的,表示这个方法将扩展 string 类型。接下来的两个参数分别是 toFind 字符串和一个布尔值 ignoreCase,用于指示是否忽略大小写进行匹配。

使用扩展方法

接下来,我们可以在程序中使用这个扩展方法:

class Program
{
    static void Main()
    {
        string text = "Hello world, hello everyone!";
        string pattern = "hello";

        // 计算不区分大小写的出现次数
        int countIgnoreCase = text.CountOccurrences(pattern, true);
        Console.WriteLine($"Pattern '{pattern}' occurs {countIgnoreCase} times (case-insensitive).");

        // 计算区分大小写的出现次数
        int countCaseSensitive = text.CountOccurrences(pattern, false);
        Console.WriteLine($"Pattern '{pattern}' occurs {countCaseSensitive} times (case-sensitive).");
    }
}

在这个示例中,我们创建了一个字符串 text 和一个子串 pattern,然后分别使用 CountOccurrences 方法来计算 pattern 在 text 中出现的次数,一次是忽略大小写的情况,一次是区分大小写的情况。

输出结果

当你运行这段代码时,应该会得到以下输出:

Pattern 'hello' occurs 2 times (case-insensitive).
Pattern 'hello' occurs 1 times (case-sensitive).

这个示例展示了如何定义一个带有多个参数的扩展方法,并且如何在实际应用中使用它。通过这种方式,你可以轻松地扩展现有类型的功能,同时保持代码的清晰和简洁。

注:接口也可以扩展

扩展方法链

定义

扩展方法链(Chaining Extension Methods)是指在一个表达式中连续使用多个扩展方法,从而使代码更加简洁和易读。这种方法在 C# 中非常常见,尤其是在处理集合和其他类型时。通过链式调用,你可以将多个操作串联在一起,形成流畅的代码风格。

示例

比如去除前后空白字符、转换为小写、替换某些字符等。我们可以定义一系列扩展方法,并将它们链式调用。

定义扩展方法

TrimAndToLower:去除前后空白字符并转换为小写。

ReplaceChars:替换字符串中的某些字符。

using System;

public static class StringExtensions
{
    // 扩展方法:去除前后空白字符并转换为小写
    public static string TrimAndToLower(this string str)
    {
        return str.Trim().ToLower();
    }

    // 扩展方法:替换字符串中的某些字符
    public static string ReplaceChars(this string str, char oldChar, char newChar)
    {
        return str.Replace(oldChar, newChar);
    }
}

使用扩展方法

class Program
{
    static void Main()
    {
        string originalText = " Hello, World! ";
        
        // 链式调用扩展方法
        string processedText = originalText
            .TrimAndToLower() // 去除前后空白字符并转换为小写
            .ReplaceChars('!', '?'); // 替换 '!' 为 '?'

        Console.WriteLine("Original Text: " + originalText);
        Console.WriteLine("Processed Text: " + processedText);
    }
}

输出结果

Original Text:   Hello, World! 
Processed Text:  hello, world?

二义性与解析

命名空间

只有包含扩展方法的类在作用域内时(一般通过导入其所在的命名空间)我们才能够访问扩展方法。否则,编译时出错。

扩展方法与实例方法-优先级

任何兼容的实例方法的优先级总是高于扩展方法

示例

public static class ExtensionMethods
{
    public static string ToUpperCase(this string str)
    {
        return str.ToUpper();
    }
}

public  class Test
{
    public  string ToUpperCase(this string str)
    {
        return str.ToUpper();
    }
}

上例中,如果使用ToUpperCase方法会调用Test的

上例中,只能通过普通的静态调用语法调用扩展方法:及ExtensionMethods.ToUpperCase(...)

扩展方法与扩展方法-优先级

如果两个扩展方法签名相同,则扩展方法必须作为一个普通的静态方法调用才能进行区分。(方法签名相同:方法名称和参数列表【参数的数量、类型及参数的顺序】相同;方法签名不包括方法的返回类型,也不包括参数的名称)

使用更具体的参数的方法优先级更高。

public static class ExtensionMethods
{
    public static string ToUpperCase(this string str)
    {
        。。。。。
    }
}

public static class Test
{
    public static string ToUpperCase(this object str)
    {
      。。。。。
    }
}

下列代码将调用ExtensionMethods.ToUpperCase方法:

var a="aaaa".ToUpperCase();

注意:类型和结构体都比接口更加具体。

小白一枚~

大家一起学习~

  • 15
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值