using System.Text.RegularExpressions;
namespace DemoApp
{
public static class StringExtensions
{
///
/// 验证电子邮件地址
///
public static bool IsEmailAddress(this string email)
{
string pattern =
"^[a-zA-Z][\\w\\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\\w\\.-]*[a-zA-Z0-9]\\.[a-zA-Z][a-zA-Z\\.]*[a-zA-Z]$";
return Regex.Match(email, pattern).Success;
}
///
/// 验证字符串是否有效 IPv4
/// 正则表达式取自正则表达式参考
///
public static bool IsValidIPv4(this string val)
{
if (string.IsNullOrEmpty(val))
{
return false;
}
return Regex.Match(val,
@"(?:^|\s)([a-z]{3,6}(?=://))?(://)?((?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.(?:25[0-5]|2[0-4]\d|[01]?\d\d?))(?::(\d{2,5}))?(?:\s|$)")
.Success;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("[email protected]".IsEmailAddress()); //True
Console.WriteLine("sx123456@163".IsEmailAddress()); //False
Console.WriteLine("64.233.161.1470".IsValidIPv4()); //False
Console.WriteLine("64.233.161.147".IsValidIPv4()); //True
}
}
}
这里例子实现对“System.string
”类型的一些扩展方法,扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种静态方法,但可以像扩展类型上的实例方法一样进行调用。
查询功能添加到现有的 System.Collections.IEnumerable 和 System.Collections.Generic.IEnumerableusing System.Linq
指令将它们置于范围中。 然后,任何实现了 IEnumerable
如下实现排序的例子:
namespace DemoApp
{
class Program
{
static void Main(string[] args)
{
List<int> nums = new List<int> { 10, 45, 15, 39, 21, 26 };
var result = nums.OrderBy(x => x);
foreach (var i in result)
{
System.Console.Write(i + " "); // 10 15 21 26 39 45
}
}
}
}
查看OrderBy源码实现
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
...
namespace System.Linq
{
public static partial class Enumerable
{
...
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
=> new OrderedEnumerable<TSource, TKey>(source, keySelector, null, false, null);
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer)
=> new OrderedEnumerable<TSource, TKey>(source, keySelector, comparer, false, null);
...
}
}
扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定方法操作的类型。 该参数位于 this 修饰符之后。 仅当你使用 using
指令将命名空间显式导入到源代码中之后,扩展方法才位于范围中。
使用洋葱架构或其他分层应用程序设计时,通常具有一组域实体或数据传输对象,可用于跨应用程序边界进行通信。 这些对象通常不包含任何功能,或者只包含适用于应用程序的所有层的最少功能。 使用扩展方法可以添加特定于每个应用程序层的功能,而无需使用其他层中不需要的方法来向下加载对象。
using System.ComponentModel.DataAnnotations;
namespace DemoApp
{
public enum SalesReportType
{
None,
[Display(Name = "Sales Report")]
SalesReport,
[Display(Name = "Sales by store")]
SalesByStore,
[Display(Name = "Follow Up")]
OrderFollowUp,
[Display(Name = "Invoice")]
Invoice,
}
public static class SalesReportTypeExtension
{
public static string ToFileName(this SalesReportType reportTemplate)
{
switch (reportTemplate)
{
case SalesReportType.SalesReport:
return ("Sales Order Summary Report");
case SalesReportType.SalesByStore:
return ("Sales Analysys Report");
case SalesReportType.OrderFollowUp:
return ("SalesOrderFollowUp");
default:
return ("Sales Invoice");
}
}
}
public class DomainEntity
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public static class DomainEntityExtensions
{
public static string FullName(this DomainEntity value)
=> $"{value.FirstName} {value.LastName}";
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(SalesReportType.OrderFollowUp.ToFileName()); //SalesOrderFollowUp
Console.WriteLine(new DomainEntity() { Id = 666, FirstName = "Ma", LastName = "Jack" }.FullName()); //Ma Jack
}
}
}
尽管通过修改对象的代码来添加功能,或者在合理和可行的情况下派生新类型等方式仍是可取的,但扩展方法已成为在整个 .NET 生态系统中创建可重用功能的关键选项。 对于原始源不受控制、派生对象不合适或不可用,或者不应在功能适用范围之外公开功能的情况,扩展方法是一个不错的选择。
注意:
Extensions
的命名空间中具有多个包含扩展方法的静态类,则这些扩展方法将全部由 using Extensions;
指令置于范围中。https://github.com/timothymugayi/StringExtensions.git
https://referencesource.microsoft.com/
扩展方法 - C# | Microsoft Learn扩展方法 - C# | Microsoft Learn
C# 参数带this是什么意思(扩展方法)-阿里云开发者社区 (aliyun.com)