深入理解C#中的扩展方法

 更新时间:2020年06月01日 12:01:34   作者:炎炎设计  
下面这篇文章主要给大家介绍了关于c#中扩展方法的相关资料,文中通过示例代码介绍的非常详细,供大家学习参考,感兴趣的朋友可以了解下

扩展方法(Extension Methods)是C#3.0时引入的新特性,相信很多人都听过并且也都用过,最常见的是在LINQ中的使用。

不仅如此,在开发中,我们也可以创建自己扩展方法,使用它来优化类的设计、简化代码。本文将简单地介绍扩展方法的概念、定义、使用场景以及要注意的点。

一、概念

扩展方法是一种特殊类型的静态方法。对于一个C#类型,如类(包括密封类)、值类型、接口等,扩展方法可以在不改变该类型源码的前提下,为它的实例提供新的成员。因此,若要为一个框架或第三方库的某个类型增加辅助功能,通过扩展方法就可以轻而易举地实现,这也是“扩展”的意义所在。

二、如何定义

创建扩展方法很简单,有以下几个步骤:

1、创建一个静态类;

2、在其中创建一个静态方法;

3、为这个静态方法添加至少一个参数,并在第一个参数前加上this关键字,这个关键字会告诉编译器当前方法是一个扩展方法。而这个方法将成为第一个参数所属类型的新成员。

以下一个典型的扩展方法,用于为枚举值提供一个可获取其DescriptionAttribute特性值的方法:

namespace TLA. Infrastructure. Extensions
public static class EnumExtensions
{
public static string GetDescription(this Enum en)
{
Type type = en. GetType();
MemberInfo[] memInfo = type . GetMember(en. ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0] .
GetCustomAttributes (typeof (DescriptionAttribute), false);
if (attrs != null && attrs. Length > 0){
return ( (DescriptionAttribute )attrs [0]) . Description;
}
}
return en. ToString();
}
}
}

注意:只有在引用扩展方法所在的静态类的命名空间后,才能使用它;否则,直接调用会编译失败。上例中,使用该扩展方法要引用TLA.Infrastructure.Extensions命名空间。

三、何时使用

从扩展方法的概念上,不难看出,它可以用在以下几种场合:

1、要为某个类型扩展功能,但没有其源码,比如某个框架或第三方库中的一个类;例如,想要获取一个列表中所有的奇数项,就可以为IList<T>接口增加一个扩展方法,这里的IList<T>接口本身是.NET框架中的接口。

public static class IListExtentions
{
public static IEnumerable<T> OddItems<T>(this IEnumerable<T> list)
{
if (list == nu1l)
{
throw new ArgumentNullExcept ion (nameof(list)) ;
}
for (int i = 0; i < list. Count(); i++)
{
if(i%2==0)
{
yield return list. ElementAt(i);
}
}
}
}

2、即使可以访问原有类型的源码,也可以使用扩展方法为它添加辅助功能;

public interface ILog
{
void Log(string message, LogLevel logLevel);
}
public static class ILogExtensions
{
/// <summary>
///记录调试信息
/// </summary>
/// <remarks>扩 展方法,方便记录调试信息</ remarks>
public static void LogDebug(this ILog logger, string message )
{
if (true) // 判断日志配置中是否允许输入Debug类型的日志
{
logger? .Log($" {message}", LogLevel.Debug);
}
}
}

3、重用代码,使代码更简洁;由于扩展方法封装了一段完整的逻辑,所以,使用扩展方法就避免了复制粘贴代码的情况。上例中扩展方法的内容也符合这种使用场景。

四、注意事项
以下是定义与使扩展方法时的一些注意事项和最佳实践:

1、扩展方法本质上是为原有类型提供辅助功能,因此,在创建时,要确保它具有实际意义,且遵循单一职责原则;也即,不能过度使用扩展方法并且它能够完成一个具体、完整的功能;

2、扩展方法本身具有通用性,因此,它里面应避免特定的业务数据类型及其相关逻辑;

3、如果为接口增加扩展方法,扩展方法的命名空间可以与接口的一致;否则,应尽量避免与原类型写在同一命名空间下,这样会“污染”原类型。建议的做法是为扩展方法所在的类设定一个单独的命名空间,如:<Company>.<Product>.Extentions。不过,这样做也有缺点:在操作原有类型的实例时,如果不引用扩展方法所在的命名空间,那么,它就不容易被发现,而解决这个问题的办法是,尽量将扩展方法文档化,并告诉项目组的其他开发人员;

4、为接口增加扩展方法后,则所有实现此接口的类都会包含该扩展方法;
5、在扩展方法中,要对第一个参数进行非空检查,如果为空,应抛出ArgumentNullException(参数为空)异常。

相关文章

  • C# Double转化为String时的保留位数及格式方式

    C# Double转化为String时的保留位数及格式方式

    这篇文章主要介绍了C# Double转化为String时的保留位数及格式方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • C# 使用 log4net 日志组件的方法

    C# 使用 log4net 日志组件的方法

    这篇文章主要介绍了C# 使用 log4net 日志组件的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2020-12-12
  • C# 中AutoMapper的使用方法

    C# 中AutoMapper的使用方法

    这篇文章主要介绍了C# 中AutoMapper的使用方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2020-12-12
  • C#访问SqlServer设置链接超时的方法

    C#访问SqlServer设置链接超时的方法

    这篇文章主要介绍了C#访问SqlServer设置链接超时的方法,涉及CommandTimeout属性的相关设置技巧,非常简单实用,需要的朋友可以参考下
    2015-06-06
  • C#集合之队列的用法

    C#集合之队列的用法

    这篇文章介绍了C#集合之队列的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • Winform窗体如何改变语言类型

    Winform窗体如何改变语言类型

    这篇文章主要介绍了Winform窗体如何改变语言类型,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2020-11-11
  • c#文本加密程序代码示例

    c#文本加密程序代码示例

    这是一个加密软件,但只限于文本加密,加了窗口控件的滑动效果,详细看下面的代码
    2013-11-11
  • 简介C#读取XML的两种方式

    简介C#读取XML的两种方式

    在程序中访问进而操作XML文件一般有两种模型,分别是使用DOM(文档对象模型)和流模型,使用DOM的好处在于它允许编辑和更新XML文档,可以随机访问文档中的数据,可以使用XPath查询
    2013-03-03
  • Winform学生信息管理系统登陆窗体设计(1)

    Winform学生信息管理系统登陆窗体设计(1)

    这篇文章主要为大家详细介绍了Winform学生信息管理系统登陆窗体设计思路,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • C#实现六大设计原则之迪米特法则

    C#实现六大设计原则之迪米特法则

    这篇文章介绍了C#实现六大设计原则之迪米特法则的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-02-02

最新评论