欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

学习Linq之前必须要了解的扩展方法

程序员文章站 2022-07-11 07:59:26
本文主要以下面几个方面来详细讲解扩展方法:在C#3.0之前没有扩展方法的状态(或者你不会使用不知道扩展方法的时候)、扩展方法的语法及怎么使用、怎么正确的使用扩展方法; 一、首先说一下在C#3.0之前没有扩展方法的状态(或者你不会使用不知道扩展方法的时候) 1、大家在项目中肯定遇到类似这样的需求且项目 ......

      本文主要以下面几个方面来详细讲解扩展方法:在c#3.0之前没有扩展方法的状态(或者你不会使用不知道扩展方法的时候)、扩展方法的语法及怎么使用、怎么正确的使用扩展方法;

  一、首先说一下在c#3.0之前没有扩展方法的状态(或者你不会使用不知道扩展方法的时候)

        1、大家在项目中肯定遇到类似这样的需求且项目很多地方都会用到:1.需要对一个对象进行可空判断;2、对一个集合或者对象进行序列化;3、时间格式转换;4、list与datatabel之前转换等等。

              我想在没有扩展方法之前大家基本上都是做一个类似common的静态公共静态类,写一些静态方法供项目各个调用调用 如:

 public static  class common
    {
        /// <summary>
        /// 判断是否为null或者空
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static bool isnullorempty( object obj)
        {
            if (obj == null)
                return true;
            else
            {
                string objstr = obj.tostring();
                return string.isnullorempty(objstr);
            }
        }
    }

          其他类调用公共方法

 static void main(string[] args)
        {
            string str = "lxsh";
            common.isnullorempty(str);
        }

        通过这样也能完成上面所说的几个需求,但是让人感觉上端一直要显示依赖common这个静态类,项目中就会大量充斥着这样的代码,看起来不那么简洁,而且也不利于后期的链式语法编程;

        2、有时也会遇到这样的情况:你想对某个类型加一些行为(方法),但你不能改变该类型的本身,因为是别人的代码,遇到这样情况你可能会增加一个继承接口,或者一个抽象类,或者通过代理模式封装一次,这样显然能达到目的但都很麻烦;

          以上解决办法都是在没有使用扩展方法之前的解决方案,当你学会了扩展方法,你可能会有更好的选择;

    二、 接下来我们来说一下扩展方法的语法及使用

      1、扩展方法必须具备以下几个特征:

  •             必须是在非嵌套的、非泛型的静态类中
  •              必须在静态类中的静态方法
  •             至少要有一个参数
  •             第一个参数的前缀必须加this关键字且不能有任何修饰符(如:ref,out)且参数类型不能为指针

 例如:

 public static partial class extensions
    {

        public static string objecttojson(this object obj)
        {
            return jsonconvert.serializeobject(obj, new isodatetimeconverter { datetimeformat = "yyyy-mm-dd hh:mm:ss" });
        }
        /// <summary>
        /// 判断是否为null或者空
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static bool isnullorempty(this object obj)
        {
            if (obj == null)
                return true;
            else
            {
                string objstr = obj.tostring();
                return string.isnullorempty(objstr);
            }
        }

    }

    2、怎么使用扩展方法:

         先引用扩展方法静态类所在的命名空间,引用完成后,在调用的时候它在你对应类型实例上面有”智能感知“提示

学习Linq之前必须要了解的扩展方法

 

    3、扩展方法是怎么被发现调用的

    如果在using命令,将扩展方法引用到代码中,扩展方法可以像类一下不加限制地在代码中使用。如果编译器认为一个表达试好像要使用一个实例方法,但没有找到与这个方法调用兼容的实例方法,就会查找一个合适的扩展方法。它会检查导入的所有命名空间和当前命名空间中所有的扩展方法,并匹配那些从表达式类型到扩展类型存在隐式转换的扩展方法;

       简单一句话讲:编译器首先会查看这类型(包括父类)有没有对应的该实例方法,如果有该实例方法他就不会执行扩展方法,如果没有它就会找对应的扩展方法执行;

       假如有一个 student类,它有一个实例方法say,再给他加一个扩展方法say

  public  class student
    {
        public void say()
        {
            console.writeline("我是实例方法");
        }
    }


    public static class extensions
    {
        public static void say(this student student)
        {
             console.writeline("我是扩展方法");
        }

    }
  static void main(string[] args)
        {
            student student = new student();
            student.say();    
           
            console.readkey();
        }

执行结果为:

学习Linq之前必须要了解的扩展方法

     还有一种情况,对子类和父类同时加了一个一样的扩展方法,且都引用了他们名词空间,优先调用子类的扩展方法(同样适用于接口父子关系)

  public class person
    {  
    }
    public  class student:person
    {
        public void say()
        {
            console.writeline("我是实例方法");
        }
    }   

    public static class extensions
    {
        public static void say(this student student)
        {
             console.writeline("我是扩展方法");
        }
        public static void getname(this student student)
        {
            console.writeline("我是子类扩展方法");
        }
        public static void getname(this person student)
        {
            console.writeline("我是父类扩展方法");
        }

    }
  static void main(string[] args)
        {
            student student = new student();
            student.say();
            student.getname();
            console.readkey();
        }

执行结果:
学习Linq之前必须要了解的扩展方法

三、怎么正确的使用扩展方法(建议)

    接下来简单讲一下怎么正确使用扩展方法:

     1.如果在项目中使用扩展方法,首先需要要项目成员都熟悉扩展方法的使用

     2.将扩展方法单独放到一个单独的命名空间里,可有效的防止被误用,建议扩展方法所属扩展类尽量用partial类(如针对object的扩展方法命名extensions.object、针对string的扩展方法命名extensions.string),方便代码维护

 例如:extensions.object、extensions.string

namespace lucky.proect.core.extensions
{
    public static partial class extensions
    {

        public static string objecttojson(this object obj)
        {
            return jsonconvert.serializeobject(obj, new isodatetimeconverter { datetimeformat = "yyyy-mm-dd hh:mm:ss" });
        }
        /// <summary>
        /// 判断是否为null或者空
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static bool isnullorempty(this object obj)
        {
            if (obj == null)
                return true;
            else
            {
                string objstr = obj.tostring();
                return string.isnullorempty(objstr);
            }
        }

    }
}

 

namespace lucky.proect.core.extensions
{
   public static partial   class extensions
    {
          [debuggerstepthrough] //该特性是用在方法前面的,在想要跳过的方法前面加上 
        public static t fromjson<t>(this string jsonstr)
        {
            return string.isnullorempty(jsonstr) ? default(t) : jsonconvert.deserializeobject<t>(jsonstr);
        }
        /// <summary>
        /// 指示指定的字符串是 null、空或者仅由空白字符组成。
        /// </summary>
        [debuggerstepthrough] //该特性是用在方法前面的,在想要跳过的方法前面加上 
        public static bool isnullorwhitespace(this string value)
        {
            return string.isnullorwhitespace(value);
        }
        /// <summary>
        /// 将json字符串转为datatable
        /// </summary>
        /// <param name="jsonstr">json字符串</param>
        /// <returns></returns>
        public static datatable todatatable(this string jsonstr)
        {
            return jsonstr == null ? null : jsonconvert.deserializeobject<datatable>(jsonstr);
        }
    }
}

    3.尽量不在在object上面写太多的扩展方法,写之前要多加思考,不然在项目使用中任何类型智能提示出现一推扩展方法,看起来比较杂乱,针对int的扩展方法应该写在int类型上,针对datetime的扩展方法应该写在datetime类型上不应该都写在object类型上

    4.如果方法名在扩展类型中已经使用,就不要再用这个名称了,因为写了也无效;