3. Extension Methods(扩展方法)

【返回目录】

什么是扩展方法?简而言之,扩展方法是一种开发人员轻松快捷地扩展已有类型的方法定义和实现的机制。具体一点儿讲,首先,扩展方法必须是静态方法,从语法的层面来看它的调用和实例方法没有什么区别,我们还是看码说话吧:

   1: public static class ExtensionMethodDemo
   2: {
   3:     public static decimal ToMoney(this string money)
   4:     {
   5:         decimal number = 0m;
   6:  
   7:         if (!decimal.TryParse(money, out number))
   8:         {
   9:             throw new ArgumentException("Money Error Information.");
  10:         }
  11:  
  12:         return number;
  13:     }
  14:  
  15:     public static int ToAge(this string age)
  16:     {
  17:         int number = 0;
  18:  
  19:         if (!int.TryParse(age, out number))
  20:         {
  21:             throw new ArgumentException("Age Error Information.");
  22:         }
  23:  
  24:         return number;
  25:     }
  26: }

这段代码的作用是扩展string类型,使其拥有直接将string类型转换成decimal或int类型的方法,调用方法如下:

   1: static void Main(string[] args)
   2: {
   3:     string moneyInput = Console.ReadLine();
   4:  
   5:     decimal money = moneyInput.ToMoney();
   6:     int age = "24".ToAge();
   7:  
   8:     // TODO: Do something...
   9: }

不难看出,我们很轻松地就为字符串增加了两个可能在实际项目中常常需要用到的方法,同时扩展方法还传承了C#简洁高雅的语法传统,接下来我们来仔细研究一下上面的这两段代码吧。

如前所示,扩展方法必须是静态的,因此static关键字是少不了的,扩展方法只能在非泛型或非嵌套的静态类中声明,它是通过关键字this作为其第一个参数的修饰符来声明,它的第一个参数除了this关键字以外可以没有别的修饰符,同时这个参数不能是指针类型。扩展方法具备和常规静态方法一样的能力,我们不妨来看一个复杂一点儿的扩展方法:

   1: namespace DevLab
   2: {
   3:     class Program
   4:     {
   5:         static void Main(string[] args)
   6:         {
   7:             string[] names = new string[] { "ZeroCool", "Michael", "Autumoon" };
   8:             string[] nameRange = names.Range(0, 2);
   9:  
  10:             var ages = new int[] { 1, 2, 3, 4 };
  11:             var ageRange = ages.Range(1, 2);
  12:  
  13:             // TODO: Do something...
  14:         }
  15:     }
  16:  
  17:     public static class ExtensionMethodDemo
  18:     {
  19:         public static T[] Range<T>(this T[] original, int startIndex, int count)
  20:         {
  21:             if (startIndex < 0 || count < 0 || startIndex > original.Length)
  22:             {
  23:                 throw new ArgumentException("Argument Error Information.");
  24:             }
  25:  
  26:             T[] result = new T[count];
  27:             Array.Copy(original, startIndex, result, 0, count);
  28:  
  29:             return result;
  30:         }
  31:     }
  32: }

通过上面这段代码,大家可以看到扩展方法这套机制的强大之处了吧。

另外,我们需要注意的是,实例方法要优先于扩展方法的调用,在命名空间内声明的扩展方法要优先于命名空间外声明的扩展方法的调用;并且,由于就功能性而言,扩展方法相比实例方法更不明显且具有更多的限制,所以微软官方推荐大家谨慎适用扩展方法,最好只在实例方法不可行的情况下使用。最后,扩展方法目前还不支持属性、事件和操作符等类型。

posted @ 2007-11-16 02:47  麦机长  阅读(2672)  评论(0编辑  收藏  举报