C# dynamic關(guān)鍵字的使用方法
C#是一種類型安全的編程語(yǔ)言(所有表達(dá)式都能解析成某個(gè)類型的實(shí)例,在編譯器生成的代碼中,只會(huì)執(zhí)行對(duì)這個(gè)類型有效的操作),和非類型安全的語(yǔ)言相比,類型安全的優(yōu)勢(shì)就體現(xiàn)出來(lái)了:
1.許多錯(cuò)誤能在編譯時(shí)檢測(cè)到,取保代碼在執(zhí)行它之前是正確的。
2.編譯時(shí)語(yǔ)言通常能生成更小,更快的代碼。(在編譯時(shí)進(jìn)行更多的假設(shè),并在IL和元數(shù)據(jù)中落實(shí)那些假設(shè))
為了方便開(kāi)發(fā)人員使用反射或者與基本組件通信,dynamic誕生了!
一下代碼展示了如何利用反射在一個(gè)String目標(biāo)("根據(jù)我找類型")上調(diào)用一個(gè)方法(“Contains”),向它傳遞一個(gè)實(shí)參(“我只是一個(gè)string參數(shù)”),并將結(jié)果存儲(chǔ)到局部變量result中。
static void Main()
{
object target = "根據(jù)我找類型";
object arg = "我只是個(gè)string參數(shù)";
Type[] argtype = new Type[] { arg.GetType()};
System.Reflection.MethodInfo method = target.GetType().GetMethod("Contains", argtype);
object[] argm = new object[] { arg};
Boolean result=Convert.ToBoolean(method.Invoke(target,argm));
}
現(xiàn)在,有了dynamic!
static void Main()
{
dynamic target = "根據(jù)我找類型";
dynamic arg = "參數(shù)";
Boolean result = target.Contains(arg);
}
是不是發(fā)現(xiàn)有了顯著的簡(jiǎn)化。
static void Main()
{
Application excel = new Application();
excel.Visible = true;
excel.Workbooks.Add(Type.Missing);
((Range)excel.Cells[1, 1]).Value = http://www.dhdzp.com/smailxiaobai/archive/2011/11/25/"放入單元格的字符";//如果沒(méi)有dynamic類型,excel.Cells[1,1]的返回值是objec類型,必須先把它轉(zhuǎn)換為Rang類型才能訪問(wèn)Value屬性。
excel.Cells[1, 1].Value = http://www.dhdzp.com/smailxiaobai/archive/2011/11/25/"放入單元格的字符";//為COM對(duì)象生成一個(gè)可由“運(yùn)行時(shí)”調(diào)用的包裝程序集時(shí),COM方法中使用的任何variant實(shí)際都會(huì)被轉(zhuǎn)換為dynamic,這稱為動(dòng)態(tài)化(dynamicfication)。
//所以這里excel.Cells[1,1]是dynamic類型,可以不必顯示把它轉(zhuǎn)換成Range類型也能訪問(wèn)它的Value。動(dòng)態(tài)化顯著簡(jiǎn)化了與COM對(duì)象的互操作。
}
看到了dynamic的神奇,那再讓我們刨根問(wèn)底吧。
我們可以用dynamic表達(dá)式或變量調(diào)用一個(gè)成員,比如字段,屬性/索引器,方法,委托,以及一元/二元/轉(zhuǎn)換操作符,當(dāng)我們的代碼使用dynamic表達(dá)式或變量調(diào)用一個(gè)成員時(shí),編譯器會(huì)生成特殊的IL代碼來(lái)描述所需的操作。
這種特殊的代碼稱為payload(有效載荷)(這些payload代碼使用了一個(gè)稱為運(yùn)行時(shí)綁定器(runtime binder)的類),在運(yùn)行時(shí),payload代碼根據(jù)當(dāng)前由dynamic表達(dá)式/變量引用的對(duì)象的實(shí)際類型來(lái)決定具體的操作。
看這個(gè)例子:
static void Main()
{
for (int i = 0; i < 2; i++)
{
dynamic arg = (i == 0) ? (dynamic)10 : "A";
dynamic result = plus(arg);//第一次循環(huán)i==0 ,arg=10;所以調(diào)用plus時(shí),返回的是int類型。第二次是string類型。
M(result);//payload代碼判斷出傳給M的值的實(shí)際類型,然后調(diào)用相應(yīng)的重載方法。
}
Console.ReadKey();
}
static dynamic plus(dynamic arg) { return arg+arg;}
static void M(int n) { Console.WriteLine("M(int):{0}", n); }
static void M(string s) { Console.WriteLine("M(string):{0}", s); }
}
在字段類型,方法參數(shù)類型或方法類型被指定為dynamic的前提下,編譯器會(huì)將這個(gè)類型轉(zhuǎn)換為System.Object,并在元數(shù)據(jù)中向字段,參數(shù)或者返回類型應(yīng)用System.Runtime.CompilerSevices.DynamicAttribute的一個(gè)實(shí)例。如果是一個(gè)局部變量被指定為dynamic,變量類型也會(huì)成為Object,但不會(huì)向局部變量應(yīng)用DynamicAttribute,應(yīng)為它的使用限制在方法之內(nèi)。
由于dynamic就是object 所以不僅僅將dynamic變成object,或者object變成dynamic就獲取兩個(gè)不同的方法簽名。例子:
object dd(dynamic i) { return i; }
dynamic dd( object i) {return i; }
這就通不過(guò)編譯。
dynam的類型轉(zhuǎn)換:
static void Main()
{
object o = 123;//(裝箱)
Int32 n = o;//錯(cuò)誤!不允許從object到int32的隱式轉(zhuǎn)換。
Int32 n1 = (Int32)o;//從object顯示轉(zhuǎn)換到int32。(拆箱)
dynamic od = 123;//(裝箱)
dynamic os = "dsfsdf";
Int32 ns = os;//運(yùn)行時(shí)報(bào)錯(cuò)。
Int32 nd = od;//從dynamic隱式轉(zhuǎn)換為int32(拆箱)
//在本例中可看出,dynamic轉(zhuǎn)為其他類型時(shí),允許省略顯示轉(zhuǎn)型。
//但是CLR會(huì)在運(yùn)行時(shí)驗(yàn)證轉(zhuǎn)型,確保類型安全。如果對(duì)象類型不兼容要轉(zhuǎn)換成的類型,clr就會(huì)拋出一個(gè)InvalidCastException異常。
}
dynamic和var的區(qū)別:
1.var聲明一個(gè)局部變量只是一種簡(jiǎn)化語(yǔ)法,它要求編譯器根據(jù)一個(gè)表達(dá)式推斷具體的數(shù)據(jù)類型。
2.var只能用于聲明方法內(nèi)部的局部變量,而dynamic可用于局部變量,字段,參數(shù)。
3.表達(dá)式不能轉(zhuǎn)型為var,但能轉(zhuǎn)型為dynamic。
4.必須顯式初始化用var聲明的變量,但無(wú)需初始化用dynam聲明的變量。
使用dynamic應(yīng)注意:
在運(yùn)行時(shí),Microsoft.Csharp.dll必須加載到AppDomain中,這回?fù)p害程序性能,并增大內(nèi)錯(cuò)耗用,Microsoft.Csharp.dll還會(huì)加載System.dll和System.Core.dll,如果使用dynamic與COM組件互操作,還會(huì)加載System.Dynamic.dll,payload代碼執(zhí)行時(shí)會(huì)在運(yùn)行時(shí)生成動(dòng)態(tài)代碼。這些代碼會(huì)進(jìn)入一個(gè)駐留在內(nèi)存的程序集,稱為“匿名寄宿的DynamicMethods程序集”(Anonymously Hosted DynamicMethods Assembly).
當(dāng)一個(gè)特性的調(diào)用使用具有相同運(yùn)行時(shí)類型的dynamic實(shí)參發(fā)出了大量調(diào)用時(shí),這個(gè)代碼可以增強(qiáng)調(diào)度的性能。
雖然dynamic能簡(jiǎn)化語(yǔ)法,但是動(dòng)態(tài)求值功能產(chǎn)生的額外開(kāi)銷也是不容忽視的,畢竟加載所有這些程序集以及額外的內(nèi)存消耗,會(huì)對(duì)性能產(chǎn)生額外的影響。如果程序中只是一兩個(gè)地方需要?jiǎng)討B(tài)行為,或許傳統(tǒng)的做法會(huì)更加高效。
- 詳解C# 匿名對(duì)象(匿名類型)、var、動(dòng)態(tài)類型 dynamic
- C#動(dòng)態(tài)對(duì)象(dynamic)詳解(實(shí)現(xiàn)方法和屬性的動(dòng)態(tài))
- C# Dynamic關(guān)鍵字之:dynamic為什么比反射快的詳解
- C#使用dynamic類型訪問(wèn)JObject對(duì)象
- C#中dynamic關(guān)鍵字的正確用法(推薦)
- 深入淺析C#中的var和dynamic
- c#使用dynamic類型優(yōu)化反射的方法
- c# dynamic的使用詳解
- C# 反射與dynamic最佳組合示例代碼
- C#中dynamic動(dòng)態(tài)類型的具體使用
相關(guān)文章
C#代碼實(shí)現(xiàn)解析WTGPS和BD數(shù)據(jù)
在現(xiàn)代的導(dǎo)航與定位應(yīng)用中,準(zhǔn)確解析 GPS 和北斗(BD)等衛(wèi)星定位數(shù)據(jù)至關(guān)重要,本文將使用C#語(yǔ)言實(shí)現(xiàn)解析WTGPS和BD數(shù)據(jù),需要的可以了解下2025-06-06
C# 批量生成隨機(jī)密碼必須包含數(shù)字和字母并用加密算法加密
這篇文章主要介紹了C# 批量生成隨機(jī)密碼必須包含數(shù)字和字母并用加密算法加密,需要的朋友參考下2017-01-01
C#編程實(shí)現(xiàn)DataTable添加行的方法
這篇文章主要介紹了C#編程實(shí)現(xiàn)DataTable添加行的方法,結(jié)合兩個(gè)實(shí)例形式分析了C#操作DataTable實(shí)現(xiàn)動(dòng)態(tài)添加行的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
C#基礎(chǔ)知識(shí)之new關(guān)鍵字介紹
在 C# 中,new 關(guān)鍵字可用作運(yùn)算符、修飾符或約束,本文主要介紹這三種用法。2016-04-04
c#中WebService的介紹及調(diào)用方式小結(jié)
這篇文章主要給大家介紹了關(guān)于c#中的WebService及其調(diào)用方式的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11
C#連接操作 MySQL 數(shù)據(jù)庫(kù)實(shí)例(使用官方驅(qū)動(dòng))
這篇文章主要介紹了C#連接操作 MySQL 數(shù)據(jù)庫(kù)實(shí)例(使用官方驅(qū)動(dòng)),本文講解了C#中的Mysql連接方法和SQL操作方法,需要的朋友可以參考下2015-02-02

