建議15 使用dynamic來簡化反射實現

2022-03-11 12:12:42 字數 3092 閱讀 6104

建議15: 使用dynamic來簡化反射實現

dynamic是framework

4.0的新特性。dynamic的出現讓c#具有了弱語言型別的特性。編譯器在編譯的時候不再對型別進行檢查,編譯器預設dynamic物件支援開發者想要的任何特性。比如,即使你對getdynamicobject方法返回的物件一無所知,也可以像如下這樣進行**的呼叫,編譯器不會報錯:

dynamic dynamicobject =getdynamicobject();

console.writeline(dynamicobject.name);

console.writeline(dynamicobject.samplemethod());

當然,如果執行時dynamicobject不包含指定的這些特性(如上文中帶返回值的方法samplemethod),執行時程式會丟擲乙個runtimebinderexception異常:

「system.dynamic.expandoobject」未包含「samplemethod」的定義。

注意 有人會將var這個關鍵字與dynamic進行比較。實際上,var和dynamic完全是兩個概念,根本不應該放在一起比較。var實際上是編譯期拋給我們的「語法糖」,一旦被編譯,編譯期會自動匹配var 變數的實際型別,並用實際型別來替換該變數的宣告,這看上去就好像我們在編碼的時候是用實際型別進行宣告的。而dynamic被編譯後,實際是乙個object型別,只不過編譯器會對dynamic型別進行特殊處理,讓它在編譯期間不進行任何的型別檢查,而是將型別檢查放到了執行期。

這從visual studio的編輯器視窗就能看出來。以var宣告的變數支援「智慧型感知」,因為visual studio能推斷出var型別的實際型別;而以dynamic宣告的變數卻不支援「智慧型感知」,因為編譯器對其執行期的型別一無所知。對dynamic變數使用「智慧型感知」,會提示「此操作將在執行時解析」。

利用dynamic的這個特性,可以簡化c#中的反射語法。在dynamic出現之前,假設存在類,**如下所示:

public

class

dynamicsample

public

int add(int a, int

b)

} 我們這樣使用反射,呼叫方**如下所示:

dynamicsample dynamicsample = new

dynamicsample();

var addmethod = typeof(dynamicsample).getmethod("

add"

);

int re = (int)addmethod.invoke(dynamicsample, new

object );

在使用dynamic後,**看上去更簡潔了,並且在可控的範圍內減少了一次拆箱的機會,**如下所示:

dynamic dynamicsample2 = new

dynamicsample();

int re2 = dynamicsample2.add(1, 2

); 我們可能會對這樣的簡化不以為然,畢竟**看起來並沒有減少多少,但是,如果考慮到效率兼優美兩個特性,那麼dynamic的優勢就顯現出來了。如果對上面的**執行1000000次,如下所示:

int times = 1000000

; dynamicsample reflectsample = new

dynamicsample();

var addmethod = typeof(dynamicsample).getmethod("

add"

);

stopwatch watch1 =stopwatch.startnew();

for (var i = 0; i < times; i++)

);

} console.writeline(

string.format("

反射耗時: 毫秒

",

watch1.elapsedmilliseconds));

dynamic dynamicsample = new

dynamicsample();

stopwatch watch2 =stopwatch.startnew();

for (int i = 0; i < times; i++)

console.writeline(

string.format("

dynamic耗時: 毫秒

",

watch2.elapsedmilliseconds));

輸出為:

反射耗時:

2575

毫秒

dynamic耗時:

76毫秒

可以看到,沒有優化的反射實現,上面這個迴圈上的執行效率大大低於dynamic實現的效果。如果對反射實現進行優化,**如下所示:

dynamicsample reflectsamplebetter = new

dynamicsample();

var addmethod2 = typeof(dynamicsample).getmethod("

add"

);

var delg = (funcint, int, int>)delegate.createdelegate(typeof

( func

int, int, int>), addmethod2);

stopwatch watch3 =stopwatch.startnew();

for (var i = 0; i < times; i++)

console.writeline(

string.format("

優化的反射耗時: 毫秒

",

watch3.elapsedmilliseconds));

輸出為:

優化的反射耗時:

12毫秒

可以看到,優化後的反射實現,其效率和dynamic在乙個數量級上。可是它帶來了效率,卻犧牲了**的整潔度,這種實現在我看來是得不償失的。所以,現在有了dynamic型別,建議大家:

始終使用dynamic來簡化反射實現。

使用dynamic來簡化反射實現

dynamic是framework4.0的新特性,dynamic的出現讓c 具有了弱語言型別的特性,編譯器在編譯的時候,不再對型別進行檢查,不會報錯,但是執行時如果執行的是不存在的屬性或者方法,執行程式還是會丟擲runtimebinderexception異常。var 與 dynamic 的區別 v...

使用dynamic來簡化反射實現,並且提高了效能。

本人 與反射的比較 首先能看到的是,dynamic與反射相比,執行相同操作所需的 少的多。如呼叫類me中的getname 方法。class me public string getname 用反射呼叫getname 方法 assembly a assembly.getexecutingassembl...

使用FileUtils來簡化檔案操作

習慣於用流的方式來操作一些文件內容時,發現fileutils這個工具類的確在這方面有更好的操作。我來做了一些小的demo 1.先看看怎麼用fileutils來建立乙個資料夾並寫入你的資料。try catch ioexception e 是不是很簡單。下面用list集合的方式寫入資料 list lin...