扩展方法简介

  以下是常规获取现在时间的一个方法。当有一天这个"yyyy-MM-dd"格式,有个需求需要在一千个方法中实现,你确定要写上一千次?不会吧!于是得想办法格式化一次便能达到目的。

 1         /// <summary>
 2         /// 静态方法,便于在Main函数中调用.
 3         /// </summary>
 4         static void ExtMethod()
 5         {
 6             DateTime now = DateTime.Now;
 7             // 时间格式 年-月-日
 8             string yyyymmddFmt = now.ToString("yyyy-MM-dd");
 9             Console.WriteLine(yyyymmddFmt);
10         }    

      你会想到写一个静态类,静态方法。于是马不停蹄的新建类··· 新建方法···

 1  /// <summary>
 2     /// 静态类,静态方法
 3     /// </summary>
 4     public static class ExtMehtodHelp
 5     {
 6         public static string FmtYYYYMMDD(DateTime date)
 7         {
 8             // 返回时间
 9             return date.ToString("yyyy-MM-dd");
10         }
11     } 

   然后在ExtMethod()方法中,便可以通过静态类点出静态方法。然后你在这一千个方法中都调用了这个静态方法。

 1         /// <summary>
 2         /// 静态方法,便于在Main函数中调用.
 3         /// </summary>
 4         static void ExtMethod()
 5         {
 6             DateTime now = DateTime.Now;
 7             // 时间格式 年-月-日
 8             string yyyymmddFmt = now.ToString("yyyy-MM-dd");
 9             // 调用静态类中的静态方法
10             string fmt01 = ExtMehtodHelp.FmtYYYYMMDD(now);
11 
12             Console.WriteLine(fmt01);
13         }    

  静态类点出静态方法,确是无可厚非的。

  如果有一种更简单的方法通过 DateTime 的 now 变量直接点出方法 FmtYYYYMMDD 的话。那多好哇,类名都用不着记了!

也可以认为 now 是一个实例,想要在实例上点出方法,那么必须是实例方法。而DateTime是微软封装好的代码,我们无法改动,所以

无法往类里面添加方法。然而现在又有这么一个需求,所以提供了一种方法叫做扩展方法。   

 1      /// <summary>
 2      /// 扩展方法的必要条件
 3      /// 1、此方法必须是一个静态方法
 4      /// 2、此方法必须放到静态类中
 5      /// 3、方法的第一个参数要以this开头,后面跟着此扩展方法所在的类型参数
 6      /// </summary>   
 7      public static class ExtMehtodHelp
 8      {
 9          // 谁点出此方法就要在其类型前加this 
10          // DateTime有个形参,表示此方法扩展至DateTime。date代表当前变量now
11          public static string FmtYYYYMMDD(this DateTime date)
12          {
13              return date.ToString("yyyy-MM-dd");
14          }
15      }

  于是在调用的时候就可以直接通过 now.FmtYYYYMMDD 来获取。在now点方法的时候,FmtYYYYMMDD方法前面是有一个向下的箭头,表示此为扩展方法。

 1         /// <summary>
 2         /// 静态方法,便于在Main函数中调用.
 3         /// </summary>
 4         static void ExtMethod()
 5         {
 6             DateTime now = DateTime.Now;
 7             // 普通形式 时间格式 年-月-日
 8             string yyyymmddFmt = now.ToString("yyyy-MM-dd");
 9             // 调用静态类中的静态方法
10             string yyyymmddFmt01 = ExtMehtodHelp.FmtYYYYMMDD(now);
11             // 调用扩展方法
12             string yyyymmddFmt02 = now.FmtYYYYMMDD();
13 
14             Console.WriteLine(yyyymmddFmt02);
15         }

  给扩展方法加多一个参数,这便是扩展方法的真正参数

 1      /// <summary>
 2      /// 扩展方法的另外一个参数,才是他的真正参数
 3      /// </summary>   
 4      public static class ExtMehtodHelp
 5      {
 6          public static string FmtYYYYMMDD(this DateTime date,string str)
 7          {
 8              return date.ToString("yyyy-MM-dd");
 9          }
10  
11      }
 1         /// <summary>
 2         /// 静态方法,便于在Main函数中调用.
 3         /// </summary>
 4         static void ExtMethod()
 5         {
 6             DateTime now = DateTime.Now;
 7             // 普通形式 时间格式 年-月-日
 8             string yyyymmddFmt = now.ToString("yyyy-MM-dd");
 9             // 调用静态类中的静态方法
10             //string yyyymmddFmt01 = ExtMehtodHelp.FmtYYYYMMDD(now);
11             // 调用扩展方法
12             // 这才是扩展方法的真正参数
13             string yyyymmddFmt02 = now.FmtYYYYMMDD("Hello");
14 
15             Console.WriteLine(yyyymmddFmt02);
16         }

  总结:通过反编译工具可看出,扩展方法其本质是静态方法。编译器认为一个表达方式是要使用一个实例方法,但是没有找到,就会检查导入的命名空间和当前命名空间里所有的扩展方法,并匹配适合的方法

.method private hidebysig static void ExtMethod() cil managed
{
    .maxstack 2
    .locals init (
        [0] valuetype [mscorlib]System.DateTime time,
        [1] string str)
    L_0000: nop 
    L_0001: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now()
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: ldstr "Hello"
    L_000d: call string D03_01新语法.ExtMehtodHelp::FmtYYYYMMDD(valuetype [mscorlib]System.DateTime, string)
    L_0012: stloc.1 
    L_0013: ldloc.1 
    L_0014: call void [mscorlib]System.Console::WriteLine(string)
    L_0019: nop 
    L_001a: ret 
}

  扩展方法的必要条件
1、此方法必须是一个静态方法
2、此方法必须放到静态类中
3、方法的第一个参数要以this开头,后面跟着此扩展方法所在的类型参数
  特点:(这里没有演示)
1、扩展方法与实例方法可以构造成重载
2、如果扩展方法的名称和参数与实例方法相同,则实例方法的优先级高于扩展方法来调用
3、扩展在父接口或父类上的扩展方法,在子类的实例中也可以调用



原文地址:https://www.cnblogs.com/lucklongwen/p/4018202.html