跟小静读CLR via C#(09)-扩展方法

简介:

对于一些现成的类,如果我们想添加一些新的方法来完善功能,但是不想改变已有的封装,也不想使用派生类,那么该怎么办呢?这里我们可以使用扩展方法。


一见钟情--初识扩展

扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。

我们首先来看个例子,有个直观的认识。一个现有的类User:

public class User
  {
      string _name;
      public User(string Name)
      {
          _name = Name;
      }
      public string Name
      {
          get { return _name; }
          set { this._name = value; }
      }
  }

现在我们想要增加一个方法来显示user信息,又不想修改User类。使用扩展方法

     image

扩展方法是一种比较特殊的使用,我们可以定义静态方法,然后在目标类型中以实例方法的语法进行调用。有了上面的定义后,当使用User实例时,会产生相应的智能感知,而且会提示是扩展方法。

    image

调用结果

User user = null;//实例为null
user.DisplayName();
user = new User("小静");//实例不为Null
user.DisplayName();
Console.Read();

image

查看ILDASM.exe,我们看到定义扩展方法后,Extension类会添加一个ExtensionAttribute标记。

image

了解扩展

怎样定义扩展方法?

  • 定义一个静态类,名称不限;
  • 定义静态方法,第一个参数类型为要扩展的目标类型;为了表明是扩展方法,还要给第一个参数添加this关键字。

编译过程识别顺序?

在上面的例子中,调用语句为user.DisplayName();,那么编译器的检查过程:

  • 首先检查变量类型User及其基类是否定义了DisplayName()实例方法,如果存在则会生成调用该方法的IL代码;
  • 如果不存在,则会继续检查静态类中是否存在一个名为DisplayName、第一个参数为User而且带有this关键字的静态方法,如果存在就会生成相应的IL代码。
  • 如果仍然不存在,则会产生编译错误。

正果守则--扩展规则

  • 扩展方法必须在非泛型静态类中声明,类名无限制,例如Extension类的名字可以任意修改后,都能正常调用扩展方法。扩展方法至少有一个参数,且第一个参数是目标扩展类型且用this关键字标识。
  • 扩展方法所在的静态类不能嵌套在另外一个类中。像下面这样定义会产生编译错误。

         image

        image

  • 扩展方法可以在不同的静态类中定义,所以不同的静态类中可能出现同名的扩展方法,编译器纠结了不知道该如何调用,只好产生编译错误。例如

          image

此时,我们不能再用实例方法的语法来调用了,只能用静态方法语法调用。

            user = new User("小静");//实例不为Null
            Extension.DisplayName(user);
            Extension1.DisplayName(user);

  • 派生类也继承了扩展方法, 例如我们定义派生类Student:

public class Student:User{}

它的智能感知,也包含了User类的扩展方法。

     image

所以在定义扩展方法时要比较注意,不能过多使用。基类中使用过多的扩展方法后,也许会使派生类中产生一些多余的智能感知。

  • 版本问题。如果某一天向目标扩展类定义了同名的方法DisplayName后,调用时就会覆盖之前的扩展方法,改变原先程序的行为。所以扩展方法要慎重使用。

         image

        image

  • 扩展方法和实例方法虽然语法看上去一样,但它俩有一个重要的区别,看下面这个调用。

User user = null;//实例为null
user.DisplayName();

实例方法调用时,对象不能为null,会产生运行时错误。

扩展方法世界上是调用静态方法,所以调用它的实例对象可以为Null。

  • 扩展接口?

除了为类型扩展方法外,还可以为接口定义扩展方法。例如

image

调用过程:

new[] { "AA", "BBB", "CCCC" }.ShowItems();
"Cathy".ShowItems();
Console.Read();

image

结局才是开始

这篇对扩展方法的介绍到这里算是happy ending了吧。其实说起这个话题,鹤冲天 兄台的研究就深入多了。我就当是抛砖引玉了,大家有兴趣的话学习他的系列c# 扩展方法奇思妙用

扩展方法好资料: 

  • MSDN: 扩展方法(C# 编程指南)

http://msdn.microsoft.com/zh-cn/library/bb383977.aspx

http://www.cnblogs.com/ldp615/archive/2009/08/07/1541404.html




    本文转自 陈敬(Cathy) 博客园博客,原文链接:http://www.cnblogs.com/janes/archive/2011/08/05/2128429.html,如需转载请自行联系原作者


相关文章
|
6月前
|
算法 C#
C#开源实用的工具类库,集成超过1000多种扩展方法
C#开源实用的工具类库,集成超过1000多种扩展方法
|
C# 开发者
C#扩展方法和工具类的区别
扩展方法和工具类的主要区别在于它们的作用。扩展方法旨在扩展现有的类,而工具类旨在提供一组通用且可靠的方法来执行某些任务。当需要扩展现有的类时,使用扩展方法;当需要实用函数来执行通用任务时,使用工具类。
85 0
|
编译器 C#
c# 自定义扩展方法
c# 自定义扩展方法
|
存储 开发框架 Java
【CLR C#】浅谈.Net的GC(垃圾回收)机制及其整体流程
在.NET程序开发中,为了将开发人员从繁琐的内存管理中解脱出来,将更多的精力花费在业务逻辑上,CLR提供了自动执行垃圾回收的机制来进行内存管理,开发人员甚至感觉不到这一过程的存在。.NET程序可以找出某个时间点上哪些已分配的内存空间没有被程序使用,并自动释放它们。自动找出并释放不再使用的内存空间机制,就称为垃圾回收机制。本文主要介绍.Net中的GC(垃圾回收)机制及其整体流程。
【CLR C#】浅谈.Net的GC(垃圾回收)机制及其整体流程
|
C#
c#中的扩展方法
c#中的扩展方法
98 0
|
SQL 存储 .NET
SQL Server CLR 使用 C# 自定义存储过程和触发器
原文:SQL Server CLR 使用 C# 自定义存储过程和触发器 这一篇博客接着上一篇博客继续介绍 SQL CLR Stored Procedure 和 CLR Trigger, 上一篇博客介绍了 SQL CLR Function 的使用,以及 CLR 程序集的注册和 CLR Function 的注册。
1002 0