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

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.mrgr.cn/news/15789.html

相关文章:

  • 【2024 CCF编程能力等级认证(GESP)C++ 】一级大纲
  • pytorch view 函数介绍
  • 【大模型项目实战】练完这些项目,天下没有再难倒你的大模型
  • 集成电路学习:什么是DAC数模转换器
  • 从开题到答辩:ChatGPT超全提示词分享!(下)【建议收藏】
  • 【C++】智能指针
  • leetcode刷题-二叉树07
  • 咬破那片叶,看天
  • 企业需求管理好帮手:10款工具深度解析
  • 大学生学习python之后,就业迷茫怎么办?
  • 【练习1】数字统计
  • 突发!Runway从HuggingFace及Github上删库跑路,技术圈震动!
  • AI大模型编写多线程并发框架(六十三):监听器优化·上
  • 在高质量视频生成文本、图像生成文本的GLM-4V-Plus技术加持下医疗未来的方向
  • CSS线性渐变拼接,一个完整的渐变容器(div),要拆分成多个渐变容器(div),并且保持渐变效果一致
  • MySQL必会知识精华5(WHERE简单子句)
  • day04-面向对象-常用API时间Arrays
  • 带你了解RS485通讯网关-天拓四方
  • 数学建模--皮尔逊相关系数、斯皮尔曼相关系数
  • 汽车信息安全--MCU Flash读保护真的没有后门吗?