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

一文帶你了解 C# DLR 的世界(DLR 探秘)

 更新時(shí)間:2020年02月22日 20:24:59   作者:沉睡的木木夕  
DLR 是 C#4.0 新引進(jìn)來(lái)的概念,其主要目的就是為了動(dòng)態(tài)綁定與交互。下面小編給大家?guī)?lái)一篇不錯(cuò)教程,一文帶你了解 C# DLR 的世界,需要的朋友可以參考下

在很久之前,我寫了一片文章詳解C# 匿名對(duì)象(匿名類型)、var、動(dòng)態(tài)類型 dynamic,可以借鑒。因?yàn)槟菚r(shí)候是心中想當(dāng)然的認(rèn)為只有反射能夠在運(yùn)行時(shí)解析對(duì)象的成員信息并調(diào)用成員方法。后來(lái)也是因?yàn)槠渌氖乱恢倍紱]有回過頭來(lái)把這一節(jié)知識(shí)給補(bǔ)上,正所謂亡羊補(bǔ)牢,讓我們現(xiàn)在來(lái)大致了解一下DLR吧。

DLR 全稱是 Dynamic Language Runtime(動(dòng)態(tài)語(yǔ)言運(yùn)行時(shí))。這很容易讓我們想到同在C#中還有一個(gè)叫 CLR 的東西,它叫 Common Language Runtime。那這兩者有什么關(guān)系呢?這個(gè)后續(xù)再說(shuō)

C#4動(dòng)態(tài)功能是Dynamic Language Runtime(動(dòng)態(tài)語(yǔ)言運(yùn)行時(shí),DLR)的一部分.DLR是添加到CLR的一系列服務(wù),它允許添加動(dòng)態(tài)語(yǔ)言,如Ruby和Python,并使C#具備和這些動(dòng)態(tài)語(yǔ)言相同的某些功能.

DLR 是 C#4.0 新引進(jìn)來(lái)的概念,其主要目的就是為了動(dòng)態(tài)綁定與交互。

C#關(guān)鍵字 dynamic

DLR 首先定義了一個(gè)核心類型概念,即動(dòng)態(tài)類型。即在運(yùn)行時(shí)確定的類型,動(dòng)態(tài)類型的成員信息、方法等都只在運(yùn)行時(shí)進(jìn)行綁定。與CLR的靜態(tài)類型相反,靜態(tài)類型都是在C#編譯期間通過一系列的規(guī)則匹配到最后的綁定。

將這種動(dòng)態(tài)進(jìn)行綁定的過程它有點(diǎn)類似反射,但其內(nèi)部卻和反射有很大的不同。這個(gè)稍微會(huì)談到。

由動(dòng)態(tài)類型構(gòu)成的對(duì)象叫動(dòng)態(tài)對(duì)象。

DLR一般有下列特點(diǎn):

  • 把CLR的所有類型全部隱式轉(zhuǎn)成dynamic。如dynamic x = GetReturnAnyCLRType()
  • 同樣,dynamic幾乎也可以轉(zhuǎn)換成CLR類型。
  • 所有含有動(dòng)態(tài)類型的表達(dá)式都是在運(yùn)行期進(jìn)行動(dòng)態(tài)計(jì)算的。

DLR發(fā)展到現(xiàn)在,我們幾乎都使用了動(dòng)態(tài)類型關(guān)鍵字 dynamic以及還有引用DLR的類庫(kù) Dapper等。

在我們不想創(chuàng)建新的靜態(tài)類做DTO映射時(shí),我們第一時(shí)間會(huì)想到動(dòng)態(tài)類型。也經(jīng)常性的將dynamic作為參數(shù)使用。

這時(shí)候我們就要注意一些 dynamic 不為大多人知的一些細(xì)節(jié)了。

不是只要含有 dynamic 的表達(dá)式都是動(dòng)態(tài)的。

什么意思呢,且看這段代碼dynamic x = "marson shine";。這句代碼很簡(jiǎn)單,就是將字符串賦值給動(dòng)態(tài)類型 x。

大家不要以為這就是動(dòng)態(tài)類型了哦,其實(shí)不是,如果單單只是這一句的話,C#編譯器在編譯期間是會(huì)把變量 x 轉(zhuǎn)變成靜態(tài)類型 object 的,等價(jià)于object x = "marson shine";??赡苡行┤藭?huì)驚訝,為什么C#編譯器最后會(huì)生成object類型的代碼。這就是接下來(lái)我們要注意的。

dynamic 于 object 的不可告人的關(guān)系

其實(shí)如果你是以 dynamic 類型為參數(shù),那么實(shí)際上它就是等于 object 類型的。換句話說(shuō),dynamic在CLR級(jí)別就是object。其實(shí)這點(diǎn)不用記,我們從編譯器生成的C#代碼就知道了。

這里我用的是dotpeek查看編譯器生成的c#代碼。

這里順便想問下各位,有沒有mac下c#反編譯的工具。求推薦

所以我們?cè)趯懼剌d方法時(shí),是不能以 object 和 dynamic 來(lái)區(qū)分的。

void DynamicMethod(object o);
void DynamicMethod(dynamic d); // error 編譯器無(wú)法通過編譯:已經(jīng)存在同名同形參的方法

如果說(shuō) dynamic 與 object 一樣,那么它與 DLR 又有什么關(guān)系呢?

其實(shí)微軟提供這么一個(gè)關(guān)鍵字,我認(rèn)為是方便提供創(chuàng)建動(dòng)態(tài)類型的快捷方式。而真正于動(dòng)態(tài)類型密切相關(guān)的是命名空間System.Dynamic下的類型。主要核心類DynamicObject,ExpandoObject,IDynamicMetaObjectProvider ,關(guān)于這三個(gè)類我們這節(jié)先不談。

DLR探秘

首先我們來(lái)大致了解C#4.0加入的重要功能 DLR,在編譯器中處于什么層次結(jié)構(gòu)。

在這里我引用 https://www.codeproject.com/Articles/42997/NET-4-0-FAQ-Part-1-The-DLR 這片文章的一副結(jié)構(gòu)圖的意思

動(dòng)態(tài)編程 = CLR + DLR

這足以說(shuō)明 DLR 在C#中的位置,雖然名字與CLR只有一個(gè)字母之差,但是它所處的層次其實(shí)是在CLR之上的。我們知道編譯器將我們寫的代碼轉(zhuǎn)換成IL,然后經(jīng)由CLR轉(zhuǎn)換成本地代碼交由CPU執(zhí)行可執(zhí)行程序。那么實(shí)際上,DLR 是在編譯期間和運(yùn)行期做了大量工作。最后還是會(huì)將C#代碼轉(zhuǎn)換成CLR靜態(tài)語(yǔ)言,然后再經(jīng)由 CLR 將代碼轉(zhuǎn)換成本地代碼執(zhí)行(如調(diào)用函數(shù)等)。

現(xiàn)在我們來(lái)簡(jiǎn)要介紹一下DLR在編譯期間做了什么。

到這里就不得不以例子來(lái)做說(shuō)明了,我們就上面的例子稍加改造一下:

// program.cs
dynamic x = "marson shine";
string v = x.Substring(6);
Console.WriteLine(v);

為了節(jié)省篇幅,我簡(jiǎn)化并改寫了難看的變量命名以及不必要的注釋。生成的代碼如下:

 object obj1 = (object) "marson shine";
 staticCallSite1 = staticCallSite1 ?? CallSite<Func<CallSite, object, int, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.None, "Substring", (IEnumerable<Type>) null, typeof (Example), (IEnumerable<CSharpArgumentInfo>) new CSharpArgumentInfo[2]
 {
 CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, (string) null),
 CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.Constant, (string) null)
 }));

 object obj2 = ((Func<CallSite, object, int, object>) staticCallSite1.Target)((CallSite) staticCallSite1, obj1, 6);
 staticCallSite2 = staticCallSite2 ?? CallSite<Action<CallSite, Type, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "WriteLine", (IEnumerable<Type>) null, typeof (Example), (IEnumerable<CSharpArgumentInfo>) new CSharpArgumentInfo[2]
 {
 CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, (string) null),
 CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, (string) null)
 }));

 ((Action<CallSite, Type, object>) staticCallSite2.Target)((CallSite) staticCallSite2, typeof (Console), obj2);

上文的兩個(gè)變量staticCallSite1,staticCallSite2 是靜態(tài)變量,起到緩存的作用。

這里涉及到了DLR核心三個(gè)概念

  1. ExpressTree(表達(dá)式樹):通過CLR運(yùn)行時(shí)用抽象語(yǔ)法樹(AST)生成代碼并執(zhí)行。并且它也是用來(lái)與動(dòng)態(tài)語(yǔ)言交互的主要工具(如Python,JavaScript 等)
  2. CallSite(調(diào)用點(diǎn)):當(dāng)我們寫的調(diào)用動(dòng)態(tài)類型的方法,這就是一個(gè)調(diào)用點(diǎn)。這些調(diào)用都是靜態(tài)函數(shù),是能夠緩存下來(lái)的,所以在后續(xù)的調(diào)用,如果發(fā)現(xiàn)是相同類型的調(diào)用,就會(huì)更快的運(yùn)行。
  3. Binder(綁定器):除了調(diào)用點(diǎn)之外,系統(tǒng)還需要知道這些方法如何調(diào)用,就比如例子中的通過調(diào)用Binder.InvokeMember方法,以及是那些對(duì)象類型調(diào)用的方法等信息。綁定器也是可以緩存的

總結(jié)

DLR運(yùn)行過程我們總結(jié)起來(lái)就是,在運(yùn)行時(shí)DLR利用編譯運(yùn)行期間生成的表達(dá)式樹、調(diào)用點(diǎn)、綁定器代碼,以及緩存機(jī)制,我們就可以做到計(jì)算的重用來(lái)達(dá)到高性能。ASP.NET頁(yè)面緩存常見的4種方式

現(xiàn)在我們就知道了為什么DLR能干出與反射相同的效果,但是性能要遠(yuǎn)比反射要高的原因了。

補(bǔ)充說(shuō)明

剛看到評(píng)論里的同學(xué)提到了reflection與dynamic的性能測(cè)試比較,發(fā)現(xiàn)反射性能占據(jù)明顯的優(yōu)勢(shì)。事實(shí)上,從那個(gè)例子來(lái)看,恰恰說(shuō)明了DLR的問題。這里我先列出他的測(cè)試代碼

const int Num = 1000 * 100;
{
 var mi = typeof(XXX).GetMethod("Go");
 var go1 = new XXX();
 for (int i = 0; i < Num; i++)
 {
 mi.Invoke(go1, null);
 }
}
{
 dynamic go1 = new XXX();
 for (int i = 0; i < Num; i++)
 {
 go1.Go();
 }
}

在這個(gè)測(cè)試中,已經(jīng)將反射出來(lái)的元數(shù)據(jù)信息緩存到局部變量 mi,所以在調(diào)用方法的時(shí)候,實(shí)際上用到的是已經(jīng)緩存下來(lái)的 mi。那么在沒有緩存優(yōu)勢(shì)的情況,說(shuō)明DLR性能是不如 MethodInfo+Invoke 的。

其實(shí)在文章總結(jié)的時(shí)候也強(qiáng)調(diào)了,利用緩存機(jī)制達(dá)到多次重復(fù)計(jì)算的重用來(lái)提高性能

那么我們?cè)诳匆粋€(gè)例子:

public void DynamicMethod(Foo f) {
 dynamic d = f;
 d.DoSomething();
}

public void ReflectionMethod(Foo f) {
 var m = typeof(Foo).GetMethod("DoSomething");
 m?.Invoke(f, null);
}

方法 DoSomething 只是一個(gè)空方法?,F(xiàn)在我們來(lái)看執(zhí)行結(jié)果

// 執(zhí)行時(shí)間
var f = new Foo();
Stopwatch sw = new Stopwatch();
int n = 10000000;
sw.Start();
for (int i = 0; i < n; i++) {
 ReflectionMethod(f);
}
sw.Stop();
Console.WriteLine("ReflectionMethod: " + sw.ElapsedMilliseconds + " ms");

sw.Restart();
for (int i = 0; i < n; i++) {
 DynamicMethod(f);
}
sw.Stop();
Console.WriteLine("DynamicMethod: " + sw.ElapsedMilliseconds + " ms");

// 輸出
ReflectionMethod: 1923 ms
DynamicMethod: 223 ms

這里我們就能明顯看出執(zhí)行時(shí)間的差距了。實(shí)際上DLR的執(zhí)行過程我用下面?zhèn)未a表示

public void DynamicMethod(Foo f) {
 dynamic d = f;
 d.DoSomething();
}
// 以下是DLR會(huì)生成大概的代碼
static DynamicCallSite fooCallSite;
public void ReflectionMethod(Foo f) {
 object d = f;
 if(fooCallSite == null) fooCallSite = new DynamicCallSite();
 fooCallSite.Invoke("Foo",d);
}

編譯器在編譯上述方法DynamicMethod時(shí),會(huì)詢問一次這個(gè)調(diào)用點(diǎn)調(diào)用的方法的類型是否是同一個(gè),如果是則直接將已經(jīng)準(zhǔn)備好的調(diào)用點(diǎn) fooCallSite 進(jìn)行調(diào)用,否則則像文章之前說(shuō)的,會(huì)生成調(diào)用點(diǎn),綁定器綁定成員信息,根據(jù)AST將表達(dá)式生成表達(dá)式樹,將這些都緩存下來(lái)。在進(jìn)行計(jì)算(調(diào)用)。

正因?yàn)槲覀冎懒薉LR的一些內(nèi)幕,所以我們自然也知道了注意該如何用 DLR,以及關(guān)鍵字 dynamic。比如我們現(xiàn)在知道了C#編譯器會(huì)將 dynamic 等同 object 對(duì)待。那么我們?cè)谑褂玫臅r(shí)候一定要注意不要被“莫名其妙”的被裝箱了,導(dǎo)致不必要的性能損失了。

至于 DLR 的應(yīng)用,特別是結(jié)合動(dòng)態(tài)語(yǔ)言進(jìn)行編程,來(lái)達(dá)到靜態(tài)語(yǔ)言動(dòng)態(tài)編程的目的。其實(shí)DLR剛出來(lái)之際,就有了如 IronPython 這樣的開源組件。這是另外一個(gè)話題,并且我們?cè)谧鰧?shí)際應(yīng)用的情況也很少,所以就沒有展開來(lái)講了。

補(bǔ)充:

DLR主要提供以下三個(gè)功能:

1.語(yǔ)言實(shí)現(xiàn)服務(wù)提供語(yǔ)言的互操作性

2.動(dòng)態(tài)語(yǔ)言運(yùn)行時(shí)服務(wù)提供動(dòng)態(tài)調(diào)用支持

3.公共腳本宿主

依托這些模塊,您可以非常輕松的做下面這些事

1.為您現(xiàn)有的.NET應(yīng)用程序,加入腳本支持

2.為您現(xiàn)有的語(yǔ)言,提供動(dòng)態(tài)知己

3.為任何對(duì)象提供動(dòng)態(tài)操作支持

4.在您的架構(gòu)中提供腳本語(yǔ)言.

參數(shù)資料:

https://www.codeproject.com/Articles/42997/NET-4-0-FAQ-Part-1-The-DLR《深入理解C#》

到此這篇關(guān)于一文帶你了解 C# DLR 的世界的文章就介紹到這了,更多相關(guān)C# DLR 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 讀取圖片像素的具體實(shí)例

    讀取圖片像素的具體實(shí)例

    C#讀取圖片像素的具體實(shí)例,需要的朋友可以參考一下
    2013-06-06
  • C#面向?qū)ο笤O(shè)計(jì)原則之組合/聚合復(fù)用原則

    C#面向?qū)ο笤O(shè)計(jì)原則之組合/聚合復(fù)用原則

    這篇文章介紹了C#面向?qū)ο笤O(shè)計(jì)原則之組合/聚合復(fù)用原則,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • c#linq里的Skip和Take實(shí)現(xiàn)分頁(yè)或遍歷

    c#linq里的Skip和Take實(shí)現(xiàn)分頁(yè)或遍歷

    LINQ的優(yōu)勢(shì)在于它提供了一種直觀、類型安全的方式來(lái)操作各種類型的數(shù)據(jù),查詢常需要獲取一部分?jǐn)?shù)據(jù),為了實(shí)現(xiàn)這一功能,LINQ提供了Take?和Skip運(yùn)算符,Take運(yùn)算符用于從一個(gè)序列中返回指定個(gè)數(shù)的元素,Skip運(yùn)算符用于從一個(gè)序列中跳過指定個(gè)數(shù)的元素
    2024-01-01
  • c#生成自定義圖片方法代碼實(shí)例

    c#生成自定義圖片方法代碼實(shí)例

    在本篇文章中我們給大家分享了關(guān)于c#生成自定義圖片方法的相關(guān)內(nèi)容,有需要的朋友們可以參考下。
    2018-10-10
  • C#?DataSet結(jié)合FlyTreeView實(shí)現(xiàn)顯示樹狀模型數(shù)據(jù)

    C#?DataSet結(jié)合FlyTreeView實(shí)現(xiàn)顯示樹狀模型數(shù)據(jù)

    NineRays.WebControls.FlyTreeView?是?9rays.net?推出的一款功能強(qiáng)大的樹狀模型數(shù)據(jù)顯示控件,本文主要介紹了如何使用其并結(jié)合?DataSet對(duì)象進(jìn)行數(shù)據(jù)顯示,感興趣的可以了解下
    2024-04-04
  • WPF實(shí)現(xiàn)XAML轉(zhuǎn)圖片的示例詳解

    WPF實(shí)現(xiàn)XAML轉(zhuǎn)圖片的示例詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用WPF實(shí)現(xiàn)XAML轉(zhuǎn)圖片,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,感興趣的小伙伴可以了解一下
    2022-11-11
  • C#實(shí)現(xiàn)異步日志記錄類的示例代碼

    C#實(shí)現(xiàn)異步日志記錄類的示例代碼

    這篇文章主要為大家詳細(xì)介紹了C#如何實(shí)現(xiàn)異步日志記錄類,從而方便下次使用,不用重復(fù)造輪子,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下
    2023-11-11
  • C#實(shí)現(xiàn)簡(jiǎn)單的點(diǎn)餐系統(tǒng)

    C#實(shí)現(xiàn)簡(jiǎn)單的點(diǎn)餐系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)簡(jiǎn)單的點(diǎn)餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • C#取得隨機(jī)顏色的方法

    C#取得隨機(jī)顏色的方法

    這篇文章主要介紹了C#取得隨機(jī)顏色的方法,通過自定義函數(shù)實(shí)現(xiàn)隨機(jī)顏色的功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-01-01
  • Silverlight實(shí)現(xiàn)星星閃爍動(dòng)畫

    Silverlight實(shí)現(xiàn)星星閃爍動(dòng)畫

    這篇文章主要為大家詳細(xì)介紹了Silverlight實(shí)現(xiàn)星星閃爍動(dòng)畫,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07

最新評(píng)論