扩展方法

1. 什么是扩展方法

   首先我们来看看扩展方法到底是什么样子的:

   

  我们定义了一个泛型集合list,我们看到很多方法有的带有一个向下的箭头,有的却没有,这些带箭头的方法就是扩展方法。

  扩展方法可以再保持原有类型的基础上,对其进行扩展。扩展方法可以是同一程序中内方法的扩展,也可以是不同程序集的方法的扩展。有了扩展方法,我们就很容易对系统添加新的功能点,甚至对第三方的程序集进行扩展。

2. 自定义扩展方法

  为了简单起见,假如有一个Person类,只有两个属性,没有任何方法

 public class Person
    {
        public int Age { get; set; }
        public string Name { get; set; }
    }

  我们对Person扩展一个方法

  /// <summary>
    /// 对Person 类型进行扩展
    /// </summary>
    public static class PersonExtension
    {
        public static void  Show(this Person person)
        {
            Console.WriteLine("name={0},age={1}",person.Name,person.Age); 
        }
        public static void PrintName(this Person person)
        {
            Console.WriteLine("我是扩展方法");
        }
    }

 

  客户端代码

 static void Main(string[] args)
        {
            Person p = new Person();
            p.Age = 24;
            p.Name = "wjw";

            p.Show();
            p.PrintName();
            Console.ReadKey();
        }

运行结果:

name=wjw,age=24
我是实例方法

 

3 本质分析

    通过反编译代码如下;

   

    可以看出来,IL代码中,扩展方法的第一个参数this没有了,这是因为这个this是给编译器用的,编译器会根据第一个被this修饰的关键字来对该类型进行扩展,但是这个语法,CLR在运行时并不知道,因此同时给该扩展方法添加一个ExtensionAttribute属性,表示这个一个扩展方法,以便在运行时CLR知道如何调用。

本质上来讲,扩展方法就是一个静态方法,其具有静态方法具有的一切功能。

 我们来看看客户端调用代码发编译后的代码:

  

 可看出
第一个扩展方法:p.PrintName();被编译成
PersonExtension::Show(class _06_扩展方法.Person) 这是调用扩展类中的扩展方法
第二个扩展方法:p.PrintName();被编译成:Person::PrintName()

3 结论
(1) 类中存在与扩展方法同名的方法,那么会先调用实例方法,即实例方法优于扩展方法
(2) 扩展方法必须是静态的,而且存在于静态非泛型的类中

4 注意
如果扩展的类的命名空间与类的命名空间不一致:有以下三种方法:
(1) 把命名空间改成一致
(2) 使用using 添加扩展类的命名空间
(3) 在web.config中添加扩展类的命名空间
posted @ 2014-10-28 21:30  透明雨  阅读(295)  评论(0)    收藏  举报