亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C# Dynamic關鍵字之:dynamic為什么比反射快的詳解

2020-01-24 03:20:27
字體:
來源:轉載
供稿:網友

Main方法如下:

復制代碼 代碼如下:

static void Main(string[] args)
{
    dynamic str = "abcd";
    Console.WriteLine(str.Length);

    Console.WriteLine();
    Console.WriteLine(str.Substring(1));


    Console.ReadLine();
}


運行,結果如下:

clip_image002

使用reflactor 反編譯下,可以看到:

完整代碼如下:

復制代碼 代碼如下:

private static void Main(string[] args)
{
      object obj1 = "abcd";
      if (Program.<Main>o__SiteContainer0.<>p__Site1 == null)
      {
            Program.<Main>o__SiteContainer0.<>p__Site1 = CallSite<Action<CallSite, Type, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "WriteLine", null, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsStaticType | CSharpArgumentInfoFlags.UseCompileTimeType, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
      }
      if (Program.<Main>o__SiteContainer0.<>p__Site2 == null)
      {
            Program.<Main>o__SiteContainer0.<>p__Site2 = CallSite<Func<CallSite, object, object>>.Create(Binder.GetMember(CSharpBinderFlags.None, "Length", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
      }
      Program.<Main>o__SiteContainer0.<>p__Site1.Target(Program.<Main>o__SiteContainer0.<>p__Site1, typeof(Console), Program.<Main>o__SiteContainer0.<>p__Site2.Target(Program.<Main>o__SiteContainer0.<>p__Site2, obj1));
      Console.WriteLine();
      if (Program.<Main>o__SiteContainer0.<>p__Site3 == null)
      {
            Program.<Main>o__SiteContainer0.<>p__Site3 = CallSite<Action<CallSite, Type, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "WriteLine", null, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsStaticType | CSharpArgumentInfoFlags.UseCompileTimeType, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
      }
      if (Program.<Main>o__SiteContainer0.<>p__Site4 == null)
      {
            Program.<Main>o__SiteContainer0.<>p__Site4 = CallSite<Func<CallSite, object, int, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.None, "Substring", null, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
      }
      Program.<Main>o__SiteContainer0.<>p__Site3.Target(Program.<Main>o__SiteContainer0.<>p__Site3, typeof(Console), Program.<Main>o__SiteContainer0.<>p__Site4.Target(Program.<Main>o__SiteContainer0.<>p__Site4, obj1, 1));
      Console.ReadLine();
}

首先編譯器會自動生成一個靜態類:如下:
復制代碼 代碼如下:

[CompilerGenerated]
private static class <Main>o__SiteContainer0
{
      // Fields
      public static CallSite<Action<CallSite, Type, object>> <>p__Site1;
      public static CallSite<Func<CallSite, object, object>> <>p__Site2;
      public static CallSite<Action<CallSite, Type, object>> <>p__Site3;
      public static CallSite<Func<CallSite, object, int, object>> <>p__Site4;
}

為什么這里有四個CallSite<T>的對象呢?在我們的代碼中

Console.WriteLine(str.Length);
Console.WriteLine();
Console.WriteLine(str.Substring(1));
一共使用了四次dynamic對象。1:Console.WriteLine(dynamic); str.Length返回dynamic2:dynamic.Length;3:Console.WriteLine(dynamic); str.Substring 返回dynamic4:dynamic.Substring(1); 1,2,3,4,分別對應上面的<>p_Site1,2,3,4;

因為1,3 都是無返回值的,所以是Action, 2,4都有返回值,所以是Func. 看上面的代碼可能還不清楚,讓我們手動的生成下代碼吧:新建類SiteContainer 來取代編譯器自動生成的類。

復制代碼 代碼如下:

[CompilerGenerated]
public static class SiteContainer
{
  // Fields
  public static CallSite<Action<CallSite, Type, object>> p__Site1;
  public static CallSite<Func<CallSite, object, object>> p__Site2;
  public static CallSite<Action<CallSite, Type, object>> p__Site3;
  public static CallSite<Func<CallSite, object, int, object>> p__Site4;
}

接著看下初始化p__Site1時的方法吧:
復制代碼 代碼如下:

if (SiteContainer.p__Site1 == null)
{
    CallSiteBinder csb= Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
        CSharpBinderFlags.ResultDiscarded,
        "WriteLine", null, typeof(Program),
        new CSharpArgumentInfo[]
        {
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsStaticType | CSharpArgumentInfoFlags.UseCompileTimeType,null),
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None,null)
        });
    SiteContainer.p__Site1 = CallSite<Action<CallSite, Type, object>>.Create(csb);
}

InvokeMember方法的簽名:public static CallSiteBinder InvokeMember(CSharpBinderFlags flags, string name, IEnumerable<Type> typeArguments, Type context, IEnumerable<CSharpArgumentInfo> argumentInfo); 1:在這里CSharpBinderFlags傳遞的是ResultDiscarded,代表結果被丟棄,   所以可以綁定到一個void的返回方法中。2:name傳遞的是”WriteLine”,要調用的方法的名稱。3:typeArguments.類型參數的列表,傳遞null。4:context: 用于指示此操作的使用位置的 System.Type,在這里是Program5:argumentInfo:參數信息,   接著看看p__Site2如何初始化的吧:
復制代碼 代碼如下:

if (SiteContainer.p__Site2 == null)
{
    CallSiteBinder csb = Microsoft.CSharp.RuntimeBinder.Binder.GetMember(
        CSharpBinderFlags.None, "Length", typeof(Program),
        new CSharpArgumentInfo[]
        {
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
        });

    SiteContainer.p__Site2 = CallSite<Func<CallSite, object, object>>.Create(csb);
}

可以看到,和p__Site1不同的是,調用的是GetMember方法。
 
既然有了兩個CallSite<T>的對象,那么它們又是如何調用的呢??
使用CallSite<T>.Target 就可以調用了。
 
image 
 
//這是編譯器生成的代碼://SiteContainer.p__Site1.Target(SiteContainer.p__Site1, typeof(Console), // SiteContainer.p__Site2.Target(SiteContainer.p__Site2, obj1) //); var pSite2Result = SiteContainer.p__Site2.Target(SiteContainer.p__Site2, obj1); SiteContainer.p__Site1.Target(SiteContainer.p__Site1, typeof(Console), pSite2Result);

 
看看如何調用的吧:
因為SiteContainer.p__Site2,是調用Length屬性
首先調用p__Site2的target方法,執行p__Site2,對象是obj1.
dlr 就會調用obj1.Length,并返回結果,所以pSite2Result=4;
接著調用p__Site1的target,來調用Console類的WriteLine方法,參數是pSite2Result.所以輸出4.
 
最后來看下dynamic是如何調用Substring方法的:

Substring方法對應的是p__Site4,因為Substring方法傳遞了個參數1,并且有返回值,所以

p__Site4對象是:

public static CallSite<Func<CallSite, object, int, object>> p__Site4;
初始化:

復制代碼 代碼如下:

if (SiteContainer.p__Site4 == null)
{
    CallSiteBinder csb = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
        CSharpBinderFlags.None, "Substring", null, typeof(Program),
        new CSharpArgumentInfo[]
        {
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
            CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant
            | CSharpArgumentInfoFlags.UseCompileTimeType, null)                       
        });
    SiteContainer.p__Site4 = CallSite<Func<CallSite, object, int, object>>.Create(csb);
}

基本和上面的p__Site1類似,只是參數信息是:CSharpArgumentInfoFlags.Constant /

因為調用了Substring(1).在編譯的時候會傳遞1進去,而1是常量。 調用如下:

復制代碼 代碼如下:

var subStringResult = SiteContainer.p__Site4.Target(SiteContainer.p__Site4, obj1, 1);
SiteContainer.p__Site1.Target(SiteContainer.p__Site1, typeof(Console), subStringResult);

解釋同上。

完整的Main函數代碼如下:

復制代碼 代碼如下:

static void Main(string[] args)
{
    object obj1 = "abcd";

    if (SiteContainer.p__Site1 == null)
    {
        CallSiteBinder csb = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
            CSharpBinderFlags.ResultDiscarded,
            "WriteLine", null, typeof(Program),
            new CSharpArgumentInfo[]
            {
                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.IsStaticType | CSharpArgumentInfoFlags.UseCompileTimeType,null),
                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None,null)
            });
        SiteContainer.p__Site1 = CallSite<Action<CallSite, Type, object>>.Create(csb);
    }

    if (SiteContainer.p__Site2 == null)
    {
        CallSiteBinder csb = Microsoft.CSharp.RuntimeBinder.Binder.GetMember(
            CSharpBinderFlags.None, "Length", typeof(Program),
            new CSharpArgumentInfo[]
            {
                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
            });

        SiteContainer.p__Site2 = CallSite<Func<CallSite, object, object>>.Create(csb);
    }

    if (SiteContainer.p__Site4 == null)
    {
        CallSiteBinder csb = Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
            CSharpBinderFlags.None, "Substring", null, typeof(Program),
            new CSharpArgumentInfo[]
            {
                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null)    
            });
        SiteContainer.p__Site4 = CallSite<Func<CallSite, object, int, object>>.Create(csb);
    }

    var lengthResult = SiteContainer.p__Site2.Target(SiteContainer.p__Site2, obj1);
    SiteContainer.p__Site1.Target(SiteContainer.p__Site1, typeof(Console), lengthResult);


    var subStringResult = SiteContainer.p__Site4.Target(SiteContainer.p__Site4, obj1, 1);
    SiteContainer.p__Site1.Target(SiteContainer.p__Site1, typeof(Console), subStringResult);

    Console.ReadLine();
}


在這里,我沒有使用p__Site3,因為p__Site3和p__Site1相同,不過為什么微軟會生成4個CallSite<T>對象,因為1 和3是完全相同的,難道是為了實現簡單?? 、幸虧還有延遲初始化,否則靜態字段這么多,不知道會對系統產生什么影響 運行,
結果如下:

 clip_image002[4]

從這個例子也可以知道為什么dynamic會比反射的速度要快了。
1:if(p__Site1)==null,p__Site1==xxx,并且p__Site1是靜態類中的靜態字段,所以有緩存效果。
2:CallSite<T>.Target: 0 級緩存 - 基于站點歷史記錄專用的委托.
使用委托來調用,自然比反射又要快一些。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲网站视频福利| 国产精品久久网| 韩国国内大量揄拍精品视频| 久久免费视频网| 日本乱人伦a精品| 久久久久女教师免费一区| 亚洲欧洲在线观看| 亚洲人成电影在线观看天堂色| 欧美电影《睫毛膏》| 91欧美精品午夜性色福利在线| 成人精品福利视频| 欧美色另类天堂2015| 日韩一区二区三区在线播放| 日韩电影第一页| 亚洲激情视频网站| 亚洲二区中文字幕| 国产精品成人观看视频国产奇米| 国产精品入口福利| 欧美美最猛性xxxxxx| 欧美另类极品videosbest最新版本| 国产女人18毛片水18精品| 欧美另类在线观看| 国产精品视频1区| 伊人激情综合网| 亚洲一区www| 亚洲成人在线视频播放| 国产精品中文在线| 欧美亚洲成人精品| 久久精品国产成人| 成人国产在线视频| 在线播放精品一区二区三区| 久久久久久久久国产精品| 亚洲视频在线免费观看| 美日韩丰满少妇在线观看| 超碰91人人草人人干| 国产午夜精品一区理论片飘花| 日韩精品久久久久久久玫瑰园| 一区二区三区日韩在线| 欧美日韩中文字幕日韩欧美| 国产精品成人免费电影| 色偷偷偷亚洲综合网另类| 日韩亚洲精品电影| 精品久久久久久久久久久久| 51色欧美片视频在线观看| 久久久久国产视频| 自拍偷拍免费精品| 午夜免费久久久久| 亚洲一区二区三区在线免费观看| 日本成人精品在线| 久久久久国色av免费观看性色| 久久精品美女视频网站| 欧美午夜片欧美片在线观看| 深夜精品寂寞黄网站在线观看| 精品高清美女精品国产区| 日韩视频免费中文字幕| 国产偷亚洲偷欧美偷精品| 91在线高清免费观看| 日韩在线观看网址| 欧美性猛交99久久久久99按摩| 国产成人福利夜色影视| 欧美韩日一区二区| 欧美日韩国产va另类| 国产成人精品电影久久久| 欧美成人手机在线| 中文字幕欧美日韩在线| 欧美在线影院在线视频| 97精品久久久中文字幕免费| 日韩成人av一区| 国产欧美va欧美va香蕉在线| 91精品免费看| 中文字幕一区电影| 亚洲欧洲日韩国产| 欧美极品少妇xxxxⅹ免费视频| 在线视频一区二区| 精品国产乱码久久久久久虫虫漫画| 成人国产在线视频| 精品欧美一区二区三区| 国产日韩在线看片| 欧美另类交人妖| 亚洲电影免费观看高清| 亚洲影影院av| 国产精品久久久久免费a∨| 欧美视频在线免费看| 九九热视频这里只有精品| 91美女高潮出水| 久久男人的天堂| 成人精品在线观看| 成人国产精品日本在线| 97香蕉超级碰碰久久免费的优势| 久久精品国产亚洲精品2020| 欧美成人剧情片在线观看| 97**国产露脸精品国产| 热久久美女精品天天吊色| 亚洲成人久久网| 国产一区二区三区在线播放免费观看| 69国产精品成人在线播放| 国产91露脸中文字幕在线| 91精品免费久久久久久久久| 亚洲a一级视频| 国产精品日韩欧美大师| 91麻豆桃色免费看| 2019中文字幕在线观看| 国产精品18久久久久久麻辣| 91产国在线观看动作片喷水| 国产一区二区三区高清在线观看| 亚洲综合社区网| 国产精品日日摸夜夜添夜夜av| 久久夜色精品国产亚洲aⅴ| 国产精品三级美女白浆呻吟| 亚洲一区二区三区香蕉| 国产精品福利小视频| 亚洲一区二区三区在线免费观看| 亚洲自拍小视频| 欧美日韩性生活视频| 国产欧美日韩免费看aⅴ视频| 亚洲一区二区久久久| 色哟哟网站入口亚洲精品| 久久精品欧美视频| 亚洲欧美日韩一区二区在线| 国产日韩精品在线播放| 在线看片第一页欧美| 深夜精品寂寞黄网站在线观看| 红桃av永久久久| 国产一区二区三区在线免费观看| 清纯唯美亚洲激情| 欧美丰满老妇厨房牲生活| 日韩一区二区三区在线播放| 亚洲激情成人网| x99av成人免费| 午夜精品美女自拍福到在线| 九九热精品视频国产| 一道本无吗dⅴd在线播放一区| 久久久久久有精品国产| 97在线观看视频国产| 最新亚洲国产精品| 这里只有视频精品| 亚洲国产成人久久综合| 国产精品久久久久久久久久99| 精品亚洲一区二区三区在线观看| 国产精品久久久久久久一区探花| 66m—66摸成人免费视频| 日韩国产在线看| 欧美高清不卡在线| 91老司机在线| 日韩精品视频在线观看网址| 久久精品一本久久99精品| www国产亚洲精品久久网站| 国产欧美日韩高清| 日韩电影中文字幕一区| 成人福利网站在线观看| 日本韩国欧美精品大片卡二| 97超级碰碰人国产在线观看| 亚洲第一区中文字幕| 久久艳片www.17c.com| 亚洲午夜国产成人av电影男同| 九九久久国产精品| 97国产一区二区精品久久呦| 国内精品国产三级国产在线专| 欧美日韩加勒比精品一区| 国产一区二区三区在线播放免费观看| 视频在线观看99| 欧美理论电影网| 国产精品国产三级国产aⅴ浪潮| 国产精品久久久久久久天堂|