开发者社区> 问答> 正文

C基础系列:扩展方法的使用

(有什么问题欢迎指教,企鹅:2172243813 更多资讯尽在通天源码论坛)

什么是扩展方法?回答这个问题之前,先看看我们一般情况下方法的调用。类似这样的通用方法你一定写过:
C#
static void Main(string[] args)
{
<div id="sina_keyword_ad_area2" newfont_family"="">  string strRes = "2013-09-0814:12:10";
   var dRes =GetDateTime(strRes);
}
//将字符串转换为日期
public static DateTime GetDateTime(string strDate)
{
   returnConvert.ToDateTime(strDate);
}
//得到非空的字符串
public static string GetNotNullStr(string strRes)
{
   if (strRes == null)
    return string.Empty;
   else
    return strRes;
}

    
static void Main(string[] args)
{
   string strRes = "2013-09-0814:12:10";
   var dRes =GetDateTime(strRes);
}
//将字符串转换为日期
public static DateTime GetDateTime(string strDate)
{
   returnConvert.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了。进入正题。

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

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

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

然后在Main方法里面调用:
C#
static void Main(string[] args)
{
   string strTest = null;
   var strRes =strTest.GetNotNullStr();
}

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

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

c#基础系列

当然除了string,你可以给.Net内置的其他对象加扩展方法,例如给DataGridViewRow的扩展方法:
C#
//DataGridViewRow的扩展方法,将当前选中行转换为对应的对象
  public static T ToObject(this DataGridViewRowitem) 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;
}

    
//DataGridViewRow的扩展方法,将当前选中行转换为对应的对象
  public static T ToObject(this DataGridViewRowitem) 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;
}

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

2、一般对象的扩展方法

和Framework内置对象一样,自定义的对象也可以增加扩展方法。直接上示例代码:
C#
public class Person
{
    public string Name { set; get; }
    public int Age { set; get; }
}

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

C#
//Person的扩展方法,根据年龄判断是否是成年人
  public static bool GetBIsChild(this PersonoPerson)
  {
    if(oPerson.Age >= 18)
       return false;
    else
       return true;
   }

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

Main方法里面调用:
C#
var oPerson1 = new Person();
oPerson1.Age = 20;
var bIsChild = oPerson1.GetBIsChild();
    
var oPerson1 = new Person();
oPerson1.Age = 20;
var bIsChild = oPerson1.GetBIsChild();

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

3、泛型对象的扩展方法

除了上面两种之外,博主发现其实可以定义一个泛型的扩展方法。那么,是不是所有的类型都可以直接使用这个扩展方法了呢?为了保持程序的严谨,下面的方法可能没有实际意义,当开发中博主觉得可能存在这种场景:
C#
public static class DataContractExtensions
{
  //测试方法
  public static T Test(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; }
}

    
public static class DataContractExtensions
{
  //测试方法
  public static T Test(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)最好保证扩展方法和调用方法在同一个命名空间下
<div newfont_family"="">
<div newfont_family"="">本文来自苦逼IT小子的新浪博客

展开
收起
通天技术 2017-09-20 15:56:38 3148 0
0 条回答
写回答
取消 提交回答
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
继承与功能组合 立即下载
JAVA反射原理以及一些常见的应用 立即下载
建立联系方法之一 立即下载