当前位置: 首页 > article >正文

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();

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

小白一枚~

大家一起学习~


http://www.kler.cn/a/289266.html

相关文章:

  • 用友U8-Cloud uapbd.refdef.query sql注入漏洞复现
  • fastadmin多个表crud连表操作步骤
  • 批量重命名Excel文件并排序
  • 蓝队知识浅谈(上)
  • 【2024软考架构案例题】你知道 Es 的几种分词器吗?Standard、Simple、WhiteSpace、Keyword 四种分词器你知道吗?
  • python: postgreSQL using psycopg2 or psycopg
  • 【微信小程序】全局数据共享 - MobX
  • xxxSendMessageBSM函数分析
  • HarmonyOS NEXT应用开发: 常用页面模板
  • 使用docker compose一键部署 Openldap
  • el-table中文排序-前端
  • Java 输入与输出之 NIO.2【AIO】【内存映射文件】【自动资源管理】探索之【四】
  • java-URLDNS 链条审计
  • 9、设计模式
  • Spring 学习笔记
  • 【Rust光年纪】解密Rust语言在经济学计算领域的全面应用与潜力展望
  • 【docker】docker 镜像仓库的管理
  • 39. 数组中出现次数超过一半的数字
  • 【专项刷题】— 哈希表
  • 阅读笔记——《阿里巴巴Java开发规范》
  • Unity实战案例 2D小游戏HappyGlass(游戏管理类脚本)
  • git进阶·团队开发的时候为何要创建临时分支来修复bug
  • 2708. 一个小组的最大实力值(24.9.3)
  • ADB 获取屏幕坐标,并模拟滑动和点击屏幕
  • 深入理解 JavaScript DOM 操作
  • js处理echarts tooltip定时轮播