建議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...