C#扩展方法(参数带this)

一个关于字符串类型扩展方法的例子

using System.Text.RegularExpressions;
namespace DemoApp
{  
    public static class StringExtensions
    {
        /// <summary>
        /// 验证电子邮件地址
        /// </summary>
        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;
        }

        /// <summary>
        /// 验证字符串是否有效 IPv4
        /// 正则表达式取自<a href="http://regexlib.com/REDetails.aspx?regexp_id=2035">正则表达式参考</a>
        /// </summary>
        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("sx123456@163.com".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​”类型的一些扩展方法,扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种静态方法,但可以像扩展类型上的实例方法一样进行调用。

常见的扩展方法——LINQ 标准查询运算符

查询功能添加到现有的 System.Collections.IEnumerableSystem.Collections.Generic.IEnumerable<T> 类型。 若要使用标准查询运算符,请先使用 using System.Linq​ 指令将它们置于范围中。 然后,任何实现了 IEnumerable<T> 的类型看起来都具有 GroupByOrderByAverage 等实例方法。 在 IEnumerable<T> 类型的实例(如 List<T>Array)后键入“dot”时,可以在 IntelliSense 语句完成中看到这些附加方法。

如下实现排序的例子:

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;​ 指令置于范围中。

参考

  • 59
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
扩展方法(Extension Method)是C# 3.0中的一个新特性,它允许程序员向已有的类添加新的方法,而无需修改原始类的定义,也无需继承或实现接口。扩展方法可以为任何类型添加新的方法,包括系统类型,而不需要修改原始类型的代码。 使用扩展方法能够使代码更加简洁、易读,同时也能够提高代码的复用性和可维护性。扩展方法可以应用于许多场景,例如: 1. 在不修改已有类的情况下,为其添加新的功能。 2. 扩展系统类的功能,例如为字符串添加一个新的方法,用于判断字符串是否为空。 3. 扩展第三方库的功能,例如为某个第三方库提供一个新的扩展方法。 下面是一个扩展方法的示例,为字符串类型添加了一个名为IsNullOrEmpty的扩展方法: ```csharp public static class StringExtensions { public static bool IsNullOrEmpty(this string str) { return string.IsNullOrEmpty(str); } } // 使用扩展方法 string myString = null; bool result = myString.IsNullOrEmpty(); ``` 需要注意的是,扩展方法必须声明在一个静态类中,并且必须是一个静态方法扩展方法必须以this关键字作为第一个参数,并且该参数必须是扩展方法所要扩展的类型。本例中,IsNullOrEmpty方法的第一个参数是this string str,即扩展方法所要扩展的类型是字符串类型。 总之,扩展方法C#中一个非常有用的特性,可以为程序员来便利和效率。在实际开发中,我们需要根据具体情况合理使用扩展方法,以便提高代码的可读性、可重用性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值