欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C# Dynamic關(guān)鍵字之:dynamic為什么比反射快的詳解

 更新時(shí)間:2013年05月14日 10:06:13   作者:  
本篇文章是對(duì)C#中dynamic為什么比反射快進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下

Main方法如下:

復(fù)制代碼 代碼如下:

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

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


    Console.ReadLine();
}


運(yùn)行,結(jié)果如下:

clip_image002

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

完整代碼如下:

復(fù)制代碼 代碼如下:

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();
}

首先編譯器會(huì)自動(dòng)生成一個(gè)靜態(tài)類(lèi):如下:
復(fù)制代碼 代碼如下:

[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;
}

為什么這里有四個(gè)CallSite<T>的對(duì)象呢?在我們的代碼中

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

因?yàn)?,3 都是無(wú)返回值的,所以是Action, 2,4都有返回值,所以是Func. 看上面的代碼可能還不清楚,讓我們手動(dòng)的生成下代碼吧:新建類(lèi)SiteContainer 來(lái)取代編譯器自動(dòng)生成的類(lèi)。

復(fù)制代碼 代碼如下:

[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時(shí)的方法吧:
復(fù)制代碼 代碼如下:

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,代表結(jié)果被丟棄,   所以可以綁定到一個(gè)void的返回方法中。2:name傳遞的是”WriteLine”,要調(diào)用的方法的名稱(chēng)。3:typeArguments.類(lèi)型參數(shù)的列表,傳遞null。4:context: 用于指示此操作的使用位置的 System.Type,在這里是Program5:argumentInfo:參數(shù)信息,   接著看看p__Site2如何初始化的吧:
復(fù)制代碼 代碼如下:

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不同的是,調(diào)用的是GetMember方法。
 
既然有了兩個(gè)CallSite<T>的對(duì)象,那么它們又是如何調(diào)用的呢??
使用CallSite<T>.Target 就可以調(diào)用了。
 
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);

 
看看如何調(diào)用的吧:
因?yàn)镾iteContainer.p__Site2,是調(diào)用Length屬性
首先調(diào)用p__Site2的target方法,執(zhí)行p__Site2,對(duì)象是obj1.
dlr 就會(huì)調(diào)用obj1.Length,并返回結(jié)果,所以pSite2Result=4;
接著調(diào)用p__Site1的target,來(lái)調(diào)用Console類(lèi)的WriteLine方法,參數(shù)是pSite2Result.所以輸出4.
 
最后來(lái)看下dynamic是如何調(diào)用Substring方法的:

Substring方法對(duì)應(yīng)的是p__Site4,因?yàn)镾ubstring方法傳遞了個(gè)參數(shù)1,并且有返回值,所以

p__Site4對(duì)象是:

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

復(fù)制代碼 代碼如下:

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類(lèi)似,只是參數(shù)信息是:CSharpArgumentInfoFlags.Constant \

因?yàn)檎{(diào)用了Substring(1).在編譯的時(shí)候會(huì)傳遞1進(jìn)去,而1是常量。 調(diào)用如下:

復(fù)制代碼 代碼如下:

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

解釋同上。

完整的Main函數(shù)代碼如下:

復(fù)制代碼 代碼如下:

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();
}


在這里,我沒(méi)有使用p__Site3,因?yàn)閜__Site3和p__Site1相同,不過(guò)為什么微軟會(huì)生成4個(gè)CallSite<T>對(duì)象,因?yàn)? 和3是完全相同的,難道是為了實(shí)現(xiàn)簡(jiǎn)單?? 、幸虧還有延遲初始化,否則靜態(tài)字段這么多,不知道會(huì)對(duì)系統(tǒng)產(chǎn)生什么影響 運(yùn)行,
結(jié)果如下:

 clip_image002[4]

從這個(gè)例子也可以知道為什么dynamic會(huì)比反射的速度要快了。
1:if(p__Site1)==null,p__Site1==xxx,并且p__Site1是靜態(tài)類(lèi)中的靜態(tài)字段,所以有緩存效果。
2:CallSite<T>.Target: 0 級(jí)緩存 - 基于站點(diǎn)歷史記錄專(zhuān)用的委托.
使用委托來(lái)調(diào)用,自然比反射又要快一些。

相關(guān)文章

  • C#連接藍(lán)牙設(shè)備的實(shí)現(xiàn)示例

    C#連接藍(lán)牙設(shè)備的實(shí)現(xiàn)示例

    本文主要介紹了C#連接藍(lán)牙設(shè)備的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • C# .NET 中的緩存實(shí)現(xiàn)詳情

    C# .NET 中的緩存實(shí)現(xiàn)詳情

    軟件開(kāi)發(fā)中最常用的模式之一是 緩存 ,其包括進(jìn)程內(nèi)緩存、持久性進(jìn)程內(nèi)緩存和分布式緩存,本文我們將主要介紹進(jìn)程內(nèi)緩存,需要的朋友可以參考下面文章的具體內(nèi)容
    2021-09-09
  • 利用C#自定義一個(gè)時(shí)間類(lèi)型YearMonth

    利用C#自定義一個(gè)時(shí)間類(lèi)型YearMonth

    .Net6中加入了兩個(gè)新的時(shí)間類(lèi)型:DateOnly和TimeOnly,但DateOnly和TimeOnly都有相應(yīng)的應(yīng)用場(chǎng)景,所以本文就來(lái)自定義一個(gè)時(shí)間類(lèi)型YearMonth,用于解決實(shí)際項(xiàng)目開(kāi)發(fā)中的需求,希望對(duì)大家有所幫助
    2023-07-07
  • unity實(shí)現(xiàn)場(chǎng)景跳轉(zhuǎn)

    unity實(shí)現(xiàn)場(chǎng)景跳轉(zhuǎn)

    這篇文章主要為大家詳細(xì)介紹了unity實(shí)現(xiàn)場(chǎng)景跳轉(zhuǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • C#窗體-數(shù)據(jù)庫(kù)連接及登錄功能的實(shí)現(xiàn)案例

    C#窗體-數(shù)據(jù)庫(kù)連接及登錄功能的實(shí)現(xiàn)案例

    這篇文章主要介紹了C#窗體-數(shù)據(jù)庫(kù)連接及登錄功能的實(shí)現(xiàn)案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • C#_SqlDependency的使用詳解

    C#_SqlDependency的使用詳解

    SqlDependency對(duì)象表示應(yīng)用程序和 SQL Server 實(shí)例間的查詢通知依賴(lài)關(guān)系,這篇文章主要介紹了C#_SqlDependency的使用,需要的朋友可以參考下
    2023-06-06
  • C#中參數(shù)數(shù)組、引用參數(shù)和輸出參數(shù)示例詳解

    C#中參數(shù)數(shù)組、引用參數(shù)和輸出參數(shù)示例詳解

    這篇文章主要給大家介紹了關(guān)于C#中參數(shù)數(shù)組、引用參數(shù)和輸出參數(shù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • VisualStudio2019安裝C#環(huán)境的實(shí)現(xiàn)方法

    VisualStudio2019安裝C#環(huán)境的實(shí)現(xiàn)方法

    這篇文章主要介紹了VisualStudio2019安裝C#環(huán)境的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 詳解C# 代碼占用的空間

    詳解C# 代碼占用的空間

    這篇文章主要介紹了C# 代碼占用的空間的相關(guān)知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • C#運(yùn)算符重載用法實(shí)例分析

    C#運(yùn)算符重載用法實(shí)例分析

    這篇文章主要介紹了C#運(yùn)算符重載用法,實(shí)例分析了C#中運(yùn)算符重載的基本實(shí)現(xiàn)與使用技巧,需要的朋友可以參考下
    2015-07-07

最新評(píng)論