2014-05-08 60 views
2

很難想出一個好的標題,但是讓我們說我有這種情況。我有一個基類:使用從基類到通用方法列表的項目

public abstract class FooBase 
{ 

} 

而且我有一個通用的實現:

public class MyFoo<T> : FooBase where T : Bar 
{ 

} 

到目前爲止好。抽象的基礎是我可以創建這些通用項目的異構集合:

List<FooBase> list = new List<FooBase>() 
{ 
    new MyFoo<Bar1>(), 
    new MyFoo<Bar2>() 
} 

現在問題來了。我有一個通用的方法:

public void DoSomething<T>(MyFoo<T> aFoo) where T : Bar 
{ 

} 

而且這個作品時,我把它叫做一個特定Foo的一個實例:

DoSomething(new MyFoo<Bar1>()); 

但我想這將需要一個列表,並調用DoSomething功能在每個項目上:

public void DoSomethingWithList(List<FooBase> list) 
{ 
    foreach (var item in list) 
    { 
     DoSomething(item);  // doesn't work - type cannot be inferred here 
    } 
} 

那麼,有沒有辦法,在運行時讓它找出正確的類型並調用泛型函數?或者有沒有其他解決這個難題的方法?

回答

5

您可以使用動態類型 - 這將在執行時執行重載分辨率,item引用的對象類型爲實際。你可以簡單的迭代器類型更改爲dynamic這樣的:

public void DoSomethingWithList(List<FooBase> list) 
{ 
    foreach (dynamic item in list) 
    { 
     DoSomething(item); 
    } 
} 

請注意,如果你最終在你的列表中FooBase不是一個MyFoo<T>,你會得到一個執行時間的故障。

這種方法的
public void DoSomething(FooBase x) 
{ 
    // This will be called for any items in the list that aren't 
    // MyFoo<T> 
} 

缺點:您可以通過提供另一個重載避免(如果你想)

  • 它有一些性能的影響;無論這是否重要取決於您的應用程序,但您應該測試它。
  • 您會失去編譯時類型的安全性。
  • 它在C#4之前不適用,即在引入dynamic時。

如果可以避免陷入這種情況下,通過重新設計了一下,這往往是一個好主意......但有時候你真的需要這樣的事。

+0

瞭望手動插入式,因爲這不是類型安全的 – Dzior

+0

@Dzior:它是類型安全的,只是在執行時而不是編譯時。 –

+0

對不起,我的意思是強烈鍵入:) – Dzior

0

不,因爲泛型類型都在編譯時是已知的,和你的例子不提供信息給編譯器,他應該使用什麼類型的,你必須在方法調用