簡體   English   中英

動態朗。運行時與反射

[英]Dynamic Lang. Runtime vs Reflection

我打算為我的新項目使用動態關鍵字。 但在介入之前,我想了解使用動態關鍵字而不是反射的優缺點。

在專業人士的位置,我可以找到關於動態關鍵字:

  • 可讀\\可維護代碼。
  • 更少的代碼行。

雖然與使用動態關鍵字相關的負面因素,我聽到的是:

  • 影響應用程序性能。
  • Dynamic關鍵字在內部是Reflection的包裝器。
  • 動態類型可能會成為難以找到錯誤的滋生地。
  • 影響與以前的.NET版本的互操作性。

請幫助我看看我遇到的利弊是否合情合理?

請幫助我看看我遇到的利弊是否合情合理?

我對你的優點和缺點的關注是,其中一些沒有解決使用反射和使用動態之間的差異。 這種動態類型會導致在任何動態類型系統的運行時都沒有捕獲的錯誤。 反射代碼與使用動態類型的代碼一樣容易出錯。

不要在利弊方面考慮它,而是以更中性的方式思考它。 我要問的問題是“使用Reflection和使用動態類型有什么區別 ?”

第一:與反思你得到你問什么了。 使用動態,您可以獲得C#編譯器在編譯時獲得類型信息時所做的事情 這些可能是兩個完全不同的東西。 如果您有一個特定方法的MethodInfo,並且您使用特定參數調用該方法,那么這是被調用的方法 ,句點。 如果你使用“動態”,那么你要求DLR在運行時解決C#編譯器關於哪種方法是正確調用的意見。 C#編譯器可能會選擇與您實際需要的方法不同的方法。

第二:使用Reflection,您可以(如果您的代碼被授予適當的高度信任)進行私人反思。 您可以調用私有方法,讀取私有字段等。 這樣做是不是一個好主意,我不知道。 這對我來說當然是危險和愚蠢的,但我不知道你的申請是什么。 使用動態,您將獲得從C#編譯器獲得的行為; 私有方法和字段不可見。

第三:使用Reflection,您編寫的代碼看起來像一種機制 看起來您正在加載元數據源,提取某些類型,提取一些方法信息,以及通過方法信息調用接收器對象上的方法。 該方式的每一步都看起來像一個機制的操作。 通過動態,每一步都看起來像業務邏輯 您在接收器上調用方法的方式與在任何其他代碼中執行方法相同。 什么是重要的? 在某些代碼中,該機制實際上是最重要的。 在某些代碼中,機制實現的業務邏輯是最重要的。 選擇強調正確抽象級別的技術。

第四:績效成本不同。 使用Reflection,您不會獲得任何緩存行為,這意味着操作通常較慢,但維護緩存沒有內存成本,並且每個操作的成本大致相同。 使用DLR,第一次操作確實非常慢,因為它進行了大量的分析,但是分析被緩存並重用。 這會消耗內存,以換取在某些情況下后續調用中增加的速度。 我不知道你的應用程序的速度和內存使用的正確平衡是什么。

可讀\\可維護代碼

我的經歷當然是對的。

更少的代碼行。

不顯着,但它會有所幫助。

影響應用程序性能。

非常輕微。 但是,甚至沒有接近反射的方式。

Dynamic關鍵字在內部是Reflection的包裝器。

完全不真實。 動態關鍵字利用動態庫運行時。

[編輯:根據以下評論進行修正]

似乎動態語言運行時確實使用了Reflection,性能改進只是由於緩存技術。

動態類型可能會成為難以找到錯誤的滋生地。

這可能是真的; 這取決於你如何編寫代碼。 您正在有效地從代碼中刪除編譯器檢查。 如果您的測試覆蓋率良好,這可能無關緊要; 如果沒有,那么我懷疑你會遇到問題。

影響與以前的.NET版本的互操作性

不對。 我的意思是你將無法針對舊版本編譯你的代碼,但如果你想這樣做,那么你應該使用舊版本作為基礎並上傳它而不是相反。 但是,如果您想使用.NET 2庫,那么只要在app.config / web.config中包含聲明,就不應該遇到太多問題。

您缺少的一個重要項目是改進了與COM / ATL組件的互操作性。

動態和反射之間有4個很大的區別。 以下是對其的詳細說明。 參考http://www.codeproject.com/Articles/593881/What-is-the-difference-between-Reflection-and-Dyna

第1點。檢查VS Invoke

反射可以做兩件事,一件是它可以檢查元數據,二是它還具有在運行時調用方法的能力。而在Dynamic中,我們只能調用方法。 因此,如果我正在創建像visual studio IDE這樣的軟件,那么反射就是最佳選擇。 如果我只想從我的c#代碼動態調用,動態是最好的選擇。

DynamicVsReflection

Point 2. Private Vs Public Invoke

您無法使用動態調用私有方法。 在反射中,它可以調用私有方法。

第3點。緩存

Dynamic在內部使用反射,它還增加了緩存優勢。 因此,如果您只想動態調用一個對象,那么動態是最好的,因為您可以獲得性能優勢。

第4點。靜態類

動態是特定於實例的:您無權訪問靜態成員; 你必須在這些場景中使用Reflection。

在大多數情況下,使用dynamic關鍵字不會導致有意義的更短代碼。 在某些情況下,它會; 這取決於提供商,因此這是一個重要的區別。 您可能永遠不應該使用dynamic關鍵字來訪問純CLR對象; 這個好處太小了。

動態關鍵字破壞了自動重構工具,使高覆蓋率的單元測試變得更加重要; 畢竟,當你使用它時,編譯器沒有檢查任何東西。 當您使用非常穩定或固有動態類型的API進行互操作時,這並不是一個問題,但如果您使用關鍵字動態來訪問其API可能在將來發生變化的庫(例如您自己編寫的任何代碼),那么這一點尤其令人討厭)。

在有意義的地方謹慎使用關鍵字,並確保此類代碼具有充足的單元測試。 不要在不需要它或類型推斷(例如var )可以做同樣的地方使用它。

編輯:您在下面提到您正在為插件執行此操作。 托管可擴展性框架的設計考慮到了這一點 - 關鍵字dynamic和反射可能是更好的選擇。

如果您使用動態專門進行反射,那么您唯一關心的是與先前版本的兼容性。 否則它會勝過反思,因為它更具可讀性和更短。 無論如何,你將失去強烈的打字和(某些)表現。

我在使用Reflection時也會看到使用動態的所有缺點,除了與舊.NET版本的互操作性之外:

影響應用程序性能

雖然它確實影響了性能,但使用Reflection也是如此。 從我記得DLR或多或少使用Reflection第一次訪問給定類型的動態對象的方法/屬性並緩存類型/訪問目標對,以便以后訪問只是在緩存中查找,使其更快然后反思

Dynamic關鍵字在內部是Reflection的包裝器

即使這是真的(見上文),這將是一個負面因素? 它是否包裝反射不應影響您在任何重要事項中的應用。

動態類型可能會成為難以找到錯誤的滋生地

雖然這是事實,但只要你謹慎使用它就不應該是一個問題。 此外,你基本上用它作為反射的替代品(也就是說,當你想通過反射訪問某些東西時,你只使用動態的最短時間),這種錯誤的風險不應該高得多,如果你使用反射來訪問你的方法/屬性(當然,如果你把一切都變得動態,它可能會更成問題)。

影響與以前的.NET版本的互操作性

為此,你必須自己決定對你有多大關注。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM