C#扩展方法知多少

      前言:上篇 序列化效率比拼——谁是最后的赢家Newtonsoft.Json 介绍了下序列化方面的知识。看过Demo的朋友可能注意到了里面就用到过泛型的扩展方法,本篇打算总结下C#扩展方法的用法。博主打算分三个层面来介绍这个知识点,分别是:.Net内置对象的扩展方法、通常对象的扩展方法、泛型对象的扩展方法。html

     什么是扩展方法?回答这个问题以前,先看看咱们通常状况下方法的调用。相似这样的通用方法你必定写过:算法

        static void Main(string[] args)
        {

            string strRes = "2013-09-08 14:12:10";
            var dRes = GetDateTime(strRes);
        }

    
        //将字符串转换为日期
        public static DateTime GetDateTime(string strDate)
        {
            return Convert.ToDateTime(strDate);
        }

        //获得非空的字符串
        public static string GetNotNullStr(string strRes)
        {
            if (strRes == null)
                return string.Empty;
            else
                return strRes;
        }

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

 

一、.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方法放在同一个类中):post

        public static string GetNotNullStr(this string strRes)
        {
            if (strRes == null)
                return string.Empty;
            else
                return strRes ;
        }

而后在Main方法里面调用:测试

        static void Main(string[] args)
        {
            string strTest = null;
            var strRes = strTest.GetNotNullStr();
        }

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

 

     固然除了string,你能够给.Net内置的其余对象加扩展方法,例如给DataGridViewRow的扩展方法:url

//DataGridViewRow的扩展方法,将当前选中行转换为对应的对象
        public static T ToObject<T>(this DataGridViewRow item) where T:class
        {
            var model = item.DataBoundItem as T;
            if (model != null)
                return model;
            var dr = item.DataBoundItem as System.Data.DataRowView;
            model = (T)typeof(T).GetConstructor(new System.Type[] { }).Invoke(new object[] { });//反射获得泛型类的实体
            PropertyInfo[] pro = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
            Type type = model.GetType();
            foreach (PropertyInfo propertyInfo in pro)
            {
                if (Convert.IsDBNull(dr[propertyInfo.Name]))
                {
                    continue;
                }
                if (!string.IsNullOrEmpty(Convert.ToString(dr[propertyInfo.Name])))
                {
                    var propertytype = propertyInfo.PropertyType;
                }
            }
            return model;
        }
View Code

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

 

二、通常对象的扩展方法code

     和Framework内置对象同样,自定义的对象也能够增长扩展方法。直接上示例代码:

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

Main方法里面调用:

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

和string扩展方法相似,就很少作解释了。

 

三、泛型对象的扩展方法

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

public static class DataContractExtensions
{
  //测试方法
  public static T Test<T>(this T instance) where T : Test2
  {
       T Res = default(T);
       try
       {
           Res.AttrTest = instance.AttrTest.Substring(0,2);
           //其余复杂逻辑...


      }
      catch
      { }
      return Res;
  }

}

public class Test2
{
  public string AttrTest { set; get; }
}

 

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

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

(2)第一个参数必需要,而且必须是this,这是扩展方法的标识。若是方法里面还要传入其余参数,能够在后面追加参数

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

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

 

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

相关文章
相关标签/搜索