-
扩展方法——用C#编写字符串工具类增强
实例6:扩展方法——字符串工具类增强
实例介绍
在日常开发中,我们经常需要对字符串做各种处理:手机号脱敏、转驼峰命名、判断是否vb.net教程C#教程python教程SQL教程access 2010教程是数字、移除空格等。但string类是密封类(不能继承),且第三方库的类也无法修改源码——这时候扩展方法就是最佳解决方案:
它允许你在不修改原有类代码、不继承原有类的前提下,给类添加新方法,调用方式和实例方法完全一致(如str.DesensitizePhone()),让代码更自然、整洁。
本实例通过给string类扩展常用工具方法,带你掌握扩展方法的定义规则、使用场景和底层原理,学会用扩展方法优雅地增强现有类的功能。
需求分析
1.扩展string类:添加以下实用方法
1.手机号脱敏(DesensitizePhone):将13812345678转为138****5678
2.转驼峰命名(ToCamelCase):将user_name_age转为userNameAge
3.判断是否是数字(IsNumeric):支持整数、小数(如"123.45"返回true)
4.移除所有空格(RemoveAllSpaces):将"hello world 123"转为"helloworld123"
2.遵循扩展方法规则:静态类、静态方法、this关键字标记目标类型
3.测试验证:主程序调用所有扩展方法,验证功能正确性
代码实现
csharp
using System;
using System.Text.RegularExpressions;
namespace StringExtensionDemo
{
// 1. 扩展方法必须放在【静态类】中(类名通常以"XXXExtensions"命名)
public static class StringExtensions
{
// 2. 手机号脱敏:扩展string类的方法
/// <summary>
/// 手机号脱敏(前3后4保留,中间用****代替)
/// </summary>
/// <param name="str">原始手机号(需11位)</param>
/// <returns>脱敏后的字符串</returns>
public static string DesensitizePhone(this string str)
{
// 先校验输入合法性:非空且长度≥11
if (string.IsNullOrEmpty(str) || str.Length < 11)
return str; // 不满足条件直接返回原字符串
// 截取前3位+****+后4位
return $"{str.Substring(0,3)}****{str.Substring(str.Length-4)}";
}
// 3. 转驼峰命名:扩展string类的方法
public static string ToCamelCase(this string str)
{
if (string.IsNullOrEmpty(str) || !str.Contains("_"))
return str; // 无下划线直接返回原字符串
var parts = str.Split('_'); // 按下划线分割成数组
var result = parts[0].ToLower(); // 第一个单词全小写
// 后续单词首字母大写,其余小写
for (int i = 1; i < parts.Length; i++)
{
if (string.IsNullOrEmpty(parts[i])) continue; // 跳过空字符串
result += char.ToUpper(parts[i][0]) + parts[i].Substring(1).ToLower();
}
return result;
}
// 4. 判断是否是数字:扩展string类的方法
public static bool IsNumeric(this string str)
{
if (string.IsNullOrEmpty(str)) return false;
// 正则表达式匹配整数/小数(支持正负号)
return Regex.IsMatch(str, @"^[+-]?(d+(.d*)?|.d+)$");
}
//5. 移除所有空格:扩展string类的方法
public static string RemoveAllSpaces(this string str)
{
return string.IsNullOrEmpty(str) ? str : str.Replace(" ", "");
}
}
// 主程序:测试扩展方法
class Program
{
static void Main(string[] args)
{
// 测试手机号脱敏
string phone = "13812345678";
Console.WriteLine($"手机号脱敏:{phone.DesensitizePhone()}"); // 输出:138****5678
// 测试转驼峰命名
string snakeCase = "user_name_age";
Console.WriteLine($"转驼峰:{snakeCase.ToCamelCase()}"); // 输出:userNameAge
// 测试是否是数字
string num1 = "123.45";
string num2 = "-678";
string nonNum = "abc123";
Console.WriteLine($""{num1}"是数字?{num1.IsNumeric()}"); // True
Console.WriteLine($""{num2}"是数字?{num2.IsNumeric()}"); // True
Console.WriteLine($""{nonNum}"是数字?{nonNum.IsNumeric()}"); // False
// 测试移除所有空格
string spacedStr = "hello world 123";
Console.WriteLine($"移除空格:{spacedStr.RemoveAllSpaces()}"); // 输出:helloworld123
}
}
}
逐行讲解
-
扩展方法的核心定义规则
每个扩展方法必须满足三个条件:
静态类:扩展方法必须放在静态类中(如StringExtensions),类名通常以Extensions结尾,方便识别。
静态方法:扩展方法本身是静态的(如public static string DesensitizePhone(...))。
this关键字:第一个参数必须用this标记目标类型(如this string str表示给string类扩展方法)。 -
手机号脱敏方法(DesensitizePhone)
csharp
public static string DesensitizePhone(this string str)
{
if (string.IsNullOrEmpty(str) || str.Length <11) return str;
return $"{str.Substring(0,3)}****{str.Substring(str.Length-4)}";
}
this string str:标记这是给string类扩展的方法,str是调用该方法的字符串实例。
合法性校验:避免空字符串或长度不足导致的Substring异常。
字符串截取:前3位(str.Substring(0,3))+ 中间4个星号 + 后4位(str.Substring(str.Length-4))。
3. 转驼峰命名方法(ToCamelCase)
csharp
public static string ToCamelCase(this string str)
{
if (string.IsNullOrEmpty(str) || !str.Contains("_")) return str;
var parts = str.Split('_');
var result = parts[0].ToLower();
for (int i=1; i<parts.Length; i++)
{
if (string.IsNullOrEmpty(parts[i])) continue;
result += char.ToUpper(parts[i][0]) + parts[i].Substring(1).ToLower();
}
return result;
}
按下划线分割:Split('_')将user_name_age拆分为["user","name","age"]。
驼峰规则:第一个单词全小写,后续单词首字母大写(如name→Name),拼接成最终结果。
4. 数字判断方法(IsNumeric)
csharp
public static bool IsNumeric(this string str)
{
if (string.IsNullOrEmpty(str)) return false;
return Regex.IsMatch(str, @"^[+-]?(d+(.d*)?|.d+)$");
}
正则表达式:匹配正负号、整数、小数(如"123"、"-45.67"、".89"都符合规则)。
空字符串处理:直接返回false,避免正则匹配错误。
5. 移除空格方法(RemoveAllSpaces)
csharp
public static string RemoveAllSpaces(this string str)
{
return string.IsNullOrEmpty(str) ? str : str.Replace(" ", "");
}
简单高效:用Replace(" ","")移除所有空格,比循环判断更简洁。
基础知识拓展
-
扩展方法的底层原理
扩展方法是编译器的语法糖,本质是静态方法的调用。比如:
csharp
phone.DesensitizePhone();
// 编译器会自动转换为:
StringExtensions.DesensitizePhone(phone);
因此,扩展方法不能访问目标类的私有成员(因为它本质是外部静态方法),只能使用目标类的公开成员。
2. 扩展方法的注意事项
实例方法优先:如果目标类已有同名同参数的实例方法,扩展方法会被忽略(实例方法优先级更高)。
避免重名冲突:扩展方法的名称应避免与目标类的现有方法重复,建议加前缀(如DesensitizePhone而非Phone)。
命名空间可见性:扩展方法所在的命名空间必须被using引入,否则无法调用。
不能修改目标类状态:扩展方法是“只读”的,无法修改目标类的实例变量(因为不能访问私有成员)。
3. 扩展方法vs静态工具类
| 特性 | 扩展方法 | 静态工具类 |
|---|---|---|
| 调用方式 | str.Method()(自然,像实例方法) | ToolClass.Method(str)(繁琐) |
| 代码可读性 | 高,符合面向对象思维 | 低,静态调用不够直观 |
| 适用场景 | 给现有类(如string、第三方类)添加方法 | 通用工具方法(无特定目标类) |
比如:
扩展方法:phone.DesensitizePhone()
静态工具类:StringTool.DesensitizePhone(phone)
显然,扩展方法的调用更自然,代码更简洁。
4. 扩展方法的适用场景
密封类增强:给密封类(如string、int)添加方法(无法继承,只能用扩展)。
第三方类扩展:给NuGet包或框架类(如List
工具类整合:将分散的静态工具方法转为扩展方法,统一调用方式。
扩展思考
1.扩展更多方法:给string类扩展以下方法
ToPascalCase():将user_name转为UserName(首字母大写)
IsEmail():判断字符串是否是合法邮箱格式
HtmlEncode():将<转为<,避免HTML注入
2.验证实例方法优先级:给string类扩展一个ToUpper()方法,测试调用时是否优先使用系统自带的ToUpper()。
3.扩展泛型类:尝试给List
总结
扩展方法是C#中增强现有类功能的利器,它既不破坏原有类的封装,又能让代码调用更自然。核心要点:
静态类+静态方法+this关键字:扩展方法的三大定义规则。
语法糖本质:编译器将扩展方法转为静态方法调用,但调用方式像实例方法。
适用场景:密封类、第三方类的功能增强,工具类的优雅整合。
掌握扩展方法,能让你在不修改源码的前提下,轻松给任何类添加实用功能,写出更简洁、易读的代码。
本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49407.html










