2010-08-31 39 views
6

我想下面的設計沒有成功:是否有可能在C#中使用無類型的泛型列表?

abstract class Foo<T> 
{ 
    abstract T Output { get; } 
} 

class Bar 
{ 
    List<Foo> Foos; 
} 

我不喜歡使用數組列表,因爲我將不得不使用不安全的強制類型轉換來獲取類型。我希望輸入Foo,以便「輸​​出」不只是一個對象,在這種情況下,我也必須使用不安全的強制轉換。

由於我的代碼是在這個時候,我用Foo作爲一個對象與輸出無類型。

+0

完全重複:http://stackoverflow.com/questions/353126/c-multiple-generic-types-in-one-list – GameZelda 2010-09-01 01:30:56

回答

8

的例如,如果我理解正確的話,你希望它有不同類型的Output小號Foo對象的列表,對不對?由於這些輸出具有不同的類型,因此無論如何您都必須使用強制轉換。

但是,下面的想法可能會有所幫助。你怎麼樣聲明一個名爲IFoo非通用接口:¹

public interface IFoo 
{ 
    object Output { get; } 
} 

,然後實現它在你的抽象類:

abstract class Foo<T> : IFoo 
{ 
    abstract T Output { get; } 
    object IFoo.Output { get { return Output; } } 
} 

然後你就可以申報IFoo個清單:

class Bar 
{ 
    List<IFoo> Foos; 
} 

訪問這些foos時,您可以通過界面檢索輸出爲對象:

var myObject = Foos[0].Output;  // type ‘object’ 

,或者你可以嘗試去發現真正的類型,如果你知道它只能是一些特定類型之一:

if (Foos[0] is Foo<string>) 
    var myString = ((Foo<string>) Foos[0]).Output; // type ‘string’ 

你甚至可以做基於類型過濾,例如:

// Type ‘IEnumerable<string>’ (rather than ‘IEnumerable<object>’)! 
var stringFoos = Foos.OfType<Foo<string>>().Select(f => f.Output); 

¹您也可以讓這個所謂的Foo抽象基類和具有Foo<T>從中獲得。在這種情況下,您需要使用new關鍵字標記Foo<T>.Output,並使用base.Output訪問抽象基礎成員。

+0

謝謝。 :)正是我在找什麼。 – Lazlo 2010-09-01 17:54:02

0

List<Foo>無效,因爲Foo是一個模板,需要指定的類,即使它再次是通用本身(List<Foo<U> >)。

+0

泛型不是模板... – 2010-08-31 23:29:35

+0

這將是它。使Bar成爲通用的(類型參數也可以是T,或U或其他),並使用type參數來保持Foo打開。您可以根據您的控制儘可能遠地完成容器層次結構;然而,在某些時候,你必須用一個具體的類型來關閉泛型實現,以便使用類(es)。如果你想動態地做到這一點,你可以使用反射來實例化一個通用對象,該通用對象被一個Type對象或一個字符串所標識的類型關閉,但是這會很快變得混亂。 – KeithS 2010-08-31 23:32:14

0

不,您不能以這種方式使用泛型。您需要將通用類型參數添加到Bar並將其轉發給Foo<T>或在Bar類型中提供Foo<T>的已關閉實例。

第一

class Bar<T> { 
    public List<Foo<T>> Foos; 
} 
+1

我想他知道這一點。這不是他的意思。 – Timwi 2010-08-31 23:36:58

+1

@Timwi,那麼OP應該在問題中更清楚。當面對一個模棱兩可的問題時,很容易給出一個不正確的答案。對我和其他人的低估是毫無根據的。根據你的邏輯,我應該低估你對我的解釋。 – JaredPar 2010-08-31 23:51:47

+0

我同意,我也發現這樣含糊不清的問題。假設一個人自己的解釋是正確的 - 很抱歉! (當然,如果@Lazlo對此有所瞭解,這將有所幫助......)(GameZelda似乎同意我的觀點,儘管:)) – Timwi 2010-09-01 10:36:46

相關問題