• C#扩展方法知多少


    分三个层面来介绍这个知识点,分别是:.Net内置对象的扩展方法、一般对象的扩展方法、泛型对象的扩展方法。

     什么是扩展方法?回答这个问题之前,先看看我们一般情况下方法的调用。类似这样的通用方法你一定写过:

     1 static void Main(string[] args)
     2         {
     3 
     4             string strRes = "2013-09-08 14:12:10";
     5             var dRes = GetDateTime(strRes);
     6         }
     7 
     8     
     9         //将字符串转换为日期
    10         public static DateTime GetDateTime(string strDate)
    11         {
    12             return Convert.ToDateTime(strDate);
    13         }
    14 
    15         //得到非空的字符串
    16         public static string GetNotNullStr(string strRes)
    17         {
    18             if (strRes == null)
    19                 return string.Empty;
    20             else
    21                 return strRes;
    22         }

    或者在项目中有一个类似Utils的工具类,里面有多个Helper,例如StringHelper、XmlHelper等等,每个Helper里面有多个static的通用方法,然后调用的时候就是StringHelper.GetNotNullStr("aa");这样。还有一种普通的用法就是new 一个对象,通过对象去调用类里面的非static方法。反正博主刚开始做项目的时候就是这样写的。后来随着工作经验的累积,博主看到了扩展方法的写法,立马就感觉自己原来的写法太Low了。进入正题。

    1、.Net内置对象的扩展方法

    .Net内部也有很多定义的扩展方法,例如我们Linq常用的Where(x=>x==true)、Select()等等。当你转到定义的时候你很容易看出来:public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)。当然我们也可以给.Net对象新增扩展方法,比如我们要给string对象加一个扩展方法(注意这个方法不能和调用的Main方法放在同一个类中):

    1 public static string GetNotNullStr(this string strRes)
    2         {
    3             if (strRes == null)
    4                 return string.Empty;
    5             else
    6                 return strRes ;
    7         }

    然后在Main方法里面调用:

    1  static void Main(string[] args)
    2         {
    3             string strTest = null;
    4             var strRes = strTest.GetNotNullStr();
    5         }

    简单介绍:public static string GetNotNullStr(this string strRes)其中this string就表示给string对象添加扩展方法。那么在同一个命名空间下面定义的所有的string类型的变量都可以.GetNotNullStr()这样直接调用。strTest.GetNotNullStr();为什么这样调用不用传参数,是因为strTest就是作为参数传入到方法里面的。你可以试试。使用起来就和.Net framework定义的方法一样:

          当然除了string,你可以给.Net内置的其他对象加扩展方法,例如给DataGridViewRow的扩展方法:

     1 //DataGridViewRow的扩展方法,将当前选中行转换为对应的对象
     2         public static T ToObject<T>(this DataGridViewRow item) where T:class
     3         {
     4             var model = item.DataBoundItem as T;
     5             if (model != null)
     6                 return model;
     7             var dr = item.DataBoundItem as System.Data.DataRowView;
     8             model = (T)typeof(T).GetConstructor(new System.Type[] { }).Invoke(new object[] { });//反射得到泛型类的实体
     9             PropertyInfo[] pro = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
    10             Type type = model.GetType();
    11             foreach (PropertyInfo propertyInfo in pro)
    12             {
    13                 if (Convert.IsDBNull(dr[propertyInfo.Name]))
    14                 {
    15                     continue;
    16                 }
    17                 if (!string.IsNullOrEmpty(Convert.ToString(dr[propertyInfo.Name])))
    18                 {
    19                     var propertytype = propertyInfo.PropertyType;
    20                 }
    21             }
    22             return model;
    23         }

    这样看上去就像在扩展.Net Framework。有没有感觉有点高大上~

    2、一般对象的扩展方法

      和Framework内置对象一样,自定义的对象也可以增加扩展方法。直接上示例代码:

    1   public class Person
    2     {
    3         public string Name { set; get; }
    4         public int Age { set; get; }
    5     }
    1 //Person的扩展方法,根据年龄判断是否是成年人
    2         public static bool GetBIsChild(this Person oPerson)
    3         {
    4             if (oPerson.Age >= 18)
    5                 return false;
    6             else
    7                 return true;
    8         }

    Main方法里面调用:

    1 var oPerson1 = new Person();
    2 oPerson1.Age = 20;
    3 var bIsChild = oPerson1.GetBIsChild();  

    和string扩展方法类似,就不多做解释了。

    3、泛型对象的扩展方法

      除了上面两种之外,博主发现其实可以定义一个泛型的扩展方法。那么,是不是所有的类型都可以直接使用这个扩展方法了呢?为了保持程序的严谨,下面的方法可能没有实际意义,当开发中博主觉得可能存在这种场景:

     1 public static class DataContractExtensions
     2 {
     3   //测试方法
     4   public static T Test<T>(this T instance) where T : Test2
     5   {
     6        T Res = default(T);
     7        try
     8        {
     9            Res.AttrTest = instance.AttrTest.Substring(0,2);
    10            //其他复杂逻辑...
    11 
    12 
    13       }
    14       catch
    15       { }
    16       return Res;
    17   }
    18 
    19 }
    20 
    21 public class Test2
    22 {
    23   public string AttrTest { set; get; }
    24 }

    使用扩展方法有几个值得注意的地方:

    (1)扩展方法不能和调用的方法放到同一个类中

    (2)第一个参数必须要,并且必须是this,这是扩展方法的标识。如果方法里面还要传入其他参数,可以在后面追加参数

    (3)扩展方法所在的类必须是静态类

    (4)最好保证扩展方法和调用方法在同一个命名空间下

     可能你第一次使用这个会觉得很别扭。你也许会说扩展方法和我以前用的static方法无论从代码实现还是算法效率都差不多嘛,是的!确实差不多,但使用多了之后会发现它确实能帮你省去很多代码。

  • 相关阅读:
    【Salvation】——人物角色动画实现
    【Salvation】——项目进展&已取得的成果
    【Salvation】—— 项目策划&市场分析
    【前端阅读】——《程序员思维修炼》摘记&读后感&思维导图
    【性能优化】——前端性能优化之DOM
    【性能优化】——前端性能优化之图片
    【前端阅读】——《JavaScript入门经典》摘记之JavaScript与XML
    【前端阅读】——《JavaScript应用开发技术详解指南》摘记&思维导图
    【面试试题】——在浏览器输入网址,直到页面出现,之间发生了什么?
    【前端阅读】——《代码整洁之道》摘记之整洁代码、命名、函数、注释
  • 原文地址:https://www.cnblogs.com/kliine/p/10304696.html
Copyright © 2020-2023  润新知