2013-07-27 103 views
0

一個很基本的問題,考慮這個方法:動態VS的方法params對象關鍵字,返回類型

public object Foo(object bar) {... } 

VS

public dynamic Bar(dynamic bar) {... } 

儘管實際上我沒有這樣的方法簽名,這爲了簡潔起見,示例簡化了兩個方面:方法參數和返回值中的'dynamic vs object'關鍵字。

這兩種方法有什麼區別,它是否會產生相同的IL或任何性能影響?

基於參考/ workthrough /示例在那裏告訴動態就像添加了動態功能的對象,我猜兩者是相同的東西,但僅基於用法不同,如果我想添加另一個動態屬性/方法返回值。不過,我仍然懷疑是否還有其他重要的事情需要考慮。

請注意,如果我有一個像上面這樣的Bar方法的類,並使用下面的方法簽名來實現接口(反之亦然),編譯器不會抱怨任何東西。

object Bar(object bar); 

經過約3年的存在,我只是有機會使用動態功能的項目,如創建動態庫來被Web API消耗和生成(動態)JSON。

public interface IRepository 
{ 
    IEnumerable GetAll(string entityName, int skip, int take); 
    int Count(string entityName); 
    dynamic GetById(string entityName, int key); 
    void Add(string entityName, dynamic entity); 
    void Remove(string entityName, int key); 
} 

如果一個實體不具體,並且在db列中定義了entityName。我也考慮使用IEnumerableIEnumerable<dynamic>。任何想法?

+5

[「動態」和「對象」關鍵詞有什麼區別?](http://blogs.msdn.com/b/csharpfaq/archive/2010/01/25/what-is-the-difference- between-dynamic-and-object-keywords.aspx) – Zbigniew

+0

'Foo.Baz' *將導致編譯器異常,'Bar.Baz' *可能導致運行時異常。 –

+0

@PrestonGuillot不知道你的評論中有什麼'Foo.Baz'表示。 –

回答

0

dynamic in C#在IL中被翻譯爲object

.method private hidebysig instance object Foo(object bar) cil managed 
{...} 

.method private hidebysig instance object Bar(object bar) cil managed 
{ 
    .param [0] 
    .custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = (01 00 00 00) 
    .param [1] 
    .custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = (01 00 00 00) 
    ... 
} 

簽名保持不變,只有Dynamic屬性添加到返回和第一個參數。

如果您可以將參數類型從dynamic更改爲object而無需更改任何其他代碼,請執行此操作。

2

根據{... }他們肯定不會導致相同的IL!試想一下:

public object Foo(object bar) 
{ 
    Use(bar); 
} 

void Use(int i) 
{ 
} 
void Use(string s) 
{ 
} 
void Use(IConvertible c) 
{ 
} 
void Use<T>(IEnumerable<T> e) 
{ 
} 
void Use(object o) 
{ 
} 

的IL將只包含對Use最後過載的呼叫。

但是,如果參數聲明爲dynamic bar,IL將包含啓動非常複雜的重載解析算法的代碼。這可能會導致調用任何過載,或者可能導致錯誤(例如bar==null,無法確定最佳過載)。

明顯非常不同的IL。很顯然,當應用程序運行時(dynamic)必須執行整個綁定時,性能會更差,而不是在編譯該程序時一勞永逸地完成。

很明顯,dynamic案例中的緩慢和複雜的代碼可能是我們真正想要的,而不是一直呼叫相同的過載。

+0

問題是關於方法簽名,而不是關於方法的用法。 – IllidanS4