zoukankan      html  css  js  c++  java
  • 扩展方法到底做了什么

    扩展方法是.net3.5以后出现的一个比较优雅的写法,昨天讨论中有同学提出这也是通过反射实现的,不过我并不这么认为。

    扩展方法的定义必须是静态类的静态方法,对一个静态类的静态方法进行反射明显不明智。而且linq to object中大量使用扩展方法,如果是用发射实现方法调用,明显过于笨拙。

    那么事实到底如何

    先定义一个扩展方法和一个同样功能的非扩展方法


    扩展方法定义
    public static class StringHelp
        {

           
    /// <summary>
            
    /// 裁减字符串(扩展方法写法)
            
    /// </summary>
            
    /// <param name="source"></param>
            
    /// <param name="length"></param>
            
    /// <returns></returns>
            public static string CutStr(this string source, int length, string lastString)
            {
                
    if (string.IsNullOrEmpty(source))
                    
    return "";
                
    if (source.Length > length)
                {
                    
    string result = string.Empty;
                    source.ToCharArray().Take(length).ToList().ForEach(p 
    => { result += p.ToString(); });
                    
    return result + lastString;
                }
                
    else
                    
    return source;
            }
            
    /// <summary>
            
    /// 裁减字符串(非扩展方法写法)
            
    /// </summary>
            
    /// <param name="source"></param>
            
    /// <param name="length"></param>
            
    /// <returns></returns>
            public static string CutStrNew(string source, int length, string lastString)
            {
                
    if (string.IsNullOrEmpty(source))
                    
    return "";
                
    if (source.Length > length)
                {
                    
    string result = string.Empty;
                    source.ToCharArray().Take(length).ToList().ForEach(p 
    => { result += p.ToString(); });
                    
    return result + lastString;
                }
                
    else
                    
    return source;
            }
        }


    然后分别进行扩展方法调用,静态方法调用,反射调用三种调用 

    代码调用和效率比较
    class Program
        {
            
    static void Main(string[] args)
            {
                
    string str = "hello world!";
                Stopwatch watch 
    = new Stopwatch();
                Console.WriteLine(str.CutStr(
    5"..."));
                Console.WriteLine(StringHelp.StringHelp.CutStrNew(str, 
    5"..."));
                Console.WriteLine(
    typeof(StringHelp.StringHelp).GetMethod("CutStr").Invoke(nullnew object[] { str, 5"..." }));

                
    //效率比较
                watch.Start();
                
    for (int i = 0; i < 100000; i++)
                {
                    str.CutStr(
    5"...");
                }
                watch.Stop();
                
                Console.WriteLine(
    "1:"+watch.ElapsedMilliseconds);

                watch.Restart();
                
    for (int i = 0; i < 100000; i++)
                {
                    StringHelp.StringHelp.CutStrNew(str, 
    5"...");
                }
                watch.Stop();
                Console.WriteLine(
    "2:" + watch.ElapsedMilliseconds);

                watch.Restart();
                
    for (int i = 0; i < 100000; i++)
                {
                    
    typeof(StringHelp.StringHelp).GetMethod("CutStr").Invoke(nullnew object[] { str, 5"..." });
                }
                watch.Stop();
                Console.WriteLine(
    "3:" + watch.ElapsedMilliseconds);

                Console.Read();
            }
        }


    IL代码

    IL代码
    IL_0000:  nop
      IL_0001:  ldstr      
    "hello world!"
      IL_0006:  stloc.
    0
      IL_0007:  ldloc.
    0
      IL_0008:  ldc.i4.
    5
      IL_0009:  ldstr      
    "..."
      IL_000e:  call       
    string [StringHelp]StringHelp.StringHelp::CutStr(string,
                                                                            int32,
                                                                            
    string)
      IL_0013:  call       
    void [mscorlib]System.Console::WriteLine(string)
      IL_0018:  nop
      IL_0019:  ldloc.
    0
      IL_001a:  ldc.i4.
    5
      IL_001b:  ldstr      
    "..."
      IL_0020:  call       
    string [StringHelp]StringHelp.StringHelp::CutStrNew(string,
                                                                               int32,
                                                                               
    string)
      IL_0025:  call       
    void [mscorlib]System.Console::WriteLine(string)
      IL_002a:  nop
      IL_002b:  ldtoken    [StringHelp]StringHelp.StringHelp
      IL_0030:  call       
    class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
      IL_0035:  ldstr      
    "CutStr"
      IL_003a:  call       instance 
    class [mscorlib]System.Reflection.MethodInfo [mscorlib]System.Type::GetMethod(string)
      IL_003f:  ldnull
      IL_0040:  ldc.i4.
    3
      IL_0041:  newarr     [mscorlib]System.Object
      IL_0046:  stloc.
    1
      IL_0047:  ldloc.
    1
      IL_0048:  ldc.i4.
    0
      IL_0049:  ldloc.
    0
      IL_004a:  stelem.
    ref
      IL_004b:  ldloc.
    1
      IL_004c:  ldc.i4.
    1
      IL_004d:  ldc.i4.
    5
      IL_004e:  box        [mscorlib]System.Int32
      IL_0053:  stelem.
    ref
      IL_0054:  ldloc.
    1
      IL_0055:  ldc.i4.
    2
      IL_0056:  ldstr      
    "..."
      IL_005b:  stelem.
    ref
      IL_005c:  ldloc.
    1
      IL_005d:  callvirt   instance 
    object [mscorlib]System.Reflection.MethodBase::Invoke(object,
                                                                                          
    object[])
      IL_0062:  call       
    void [mscorlib]System.Console::WriteLine(object)



    三种调用的方式是这样的:

    1、string [StringHelp]StringHelp.StringHelp::CutStr(string,                                                                        int32,                                                                        string)

    2、string [StringHelp]StringHelp.StringHelp::CutStrNew(string,
                                                                               int32,
                                                                               string)

    3、instance object [mscorlib]System.Reflection.MethodBase::Invoke(object,
                                                                                          object[])


    很明显,并没有使用反射,而是编译器的语法糖,使得调用方法更为简便。在编译时期,编译器会对代码作用域范围内可见的所有静态类,且带this 特征参数的方法进行搜索,

    然后透明调用符合特征的方法。

    那么效率如何呢

     


     1、86  2、84  3、313

     效率基本没有,差别,因为其实调用的方式都没有什么区别,而且性能比反射自然要好很多。


  • 相关阅读:
    在VMWare虚拟机下的ubuntu中Samba服务的安装
    Shell表达式,如${file##*/}
    如何从官网下载QT
    SATA命令之security
    Clip
    JS判断是否在微信浏览器打开
    微信小程序请求数据报错: 如若已在管理后台更新域名配置,请刷新项目配置后重新编译项目,操作路径:“详情-域名信息”
    typeof()和instanceof的用法区别
    javascrip 对数组的操作方法
    微信小程序 修改数据,并动态渲染页面;修改数组;
  • 原文地址:https://www.cnblogs.com/brightwang/p/1744672.html
Copyright © 2011-2022 走看看