欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-09-02 08:30:23
扩展方法(extension methods)是c#3.0时引入的新特性,相信很多人都听过并且也都用过,最常见的是在linq中的使用。不仅如此,在开发中,我们也可以创建自己扩展方法,使用它来优化类的设...

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

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

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

一、概念

扩展方法是一种特殊类型的静态方法。对于一个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# 扩展