2011-04-25 74 views
0

我有兩種方法,像這樣:這是C#鑄造無用?

Foo[] GetFoos(Type t) { //do some stuff and return an array of things of type T } 

T[] GetFoos<T>() 
    where T : Foo 
{ 
    return GetFoos(typeof(T)) as T[]; 
} 

然而,這似乎總是返回null。我做錯了什麼或者這只是C#的一個缺點?

注: 我知道我可以解決這個問題:

GetFoos(typeof(T)).Cast<T>().ToArray(); 

不過,我寧願做這個wothout任何分配(在垃圾收集非常敏感的環境中工作)。

鈮++: 獎勵積分,如果你認爲一個可選的非分配解決方案

編輯: 這就提出了一個有趣的問題。 MSDN文檔如下:http://msdn.microsoft.com/en-us/library/aa664572%28v=vs.71%29.aspx表示如果存在隱式或顯式強制轉換,則強制轉換將成功。在這種情況下,有明確的演員陣容,所以演員陣容應該成功。 MSDN文檔是否錯誤?

+0

當你這樣做會發生什麼:'(T [])GetFoos(typeof運算(T))' – Will 2011-04-25 02:17:40

+0

請問:'InvalidCastException'。如果'as'返回'null',則直接投射將不會成功。 – Femaref 2011-04-25 02:18:57

+0

'GetFoos()'實現被鎖定,你不能改變它?可能最理想的情況是(除了使用泛型),如果它返回一個非特定的'Array'。然後它可以返回一個這種類型的東西,你可以安全地將它轉換爲你需要的類型。 – 2011-04-25 02:32:31

回答

2

沒有,C#鑄造是不是沒用 - 你根本無法投出Foo[]T[]其中T是一個更派生類型,因爲Foo[]可以包含到T不同的其他元素。爲什麼不將GetFoos方法調整爲GetFoos<T>()?只需要一個Type對象的方法可以很容易地轉換爲一個通用方法,您可以通過new T[]直接創建該數組。

如果這是不可能的:你需要數組提供的能力(即索引和Count之類的東西)?如果沒有,您可以使用IEnumerable<T>,而不會有太多問題。如果沒有,你不會繞過去Cast<T>.ToArray()的方式。

編輯:

有來自Foo[]沒有可能投給T[],在您的鏈接的描述是倒過來 - 你可以施放T[]Foo[]所有TFoo,但不是所有的FooT

+0

每次枚舉它的時候不幸的枚舉分配的陣列,這就是爲什麼我們」再在第一位置使用數組。服用類型的GetFoos查找在型 - 的字典陣列>富[],所以最終連通用方法將仍使用類型內部。我們不能存儲更多的具體類型數組因爲在字典中的所有值類型必須相同 – Martin 2011-04-25 02:20:58

+0

嗯,它分配一個'IEnumerator的',這是正確的,但它不會爲每次每個元素分配內存。存儲罪耗只取決於你的普查員數量。 – Femaref 2011-04-25 02:24:49

+0

對不起,通過「枚舉?」我每次啓動集合將分配(新的IEnumerator)的一個新的枚舉時間的意思。我可以嘗試p慫恿IEnumerator周圍和調用重置批次,但這是可怕的醜陋! – Martin 2011-04-25 02:26:27

1

如果您可以安排GetFoos使用new T[]創建返回數組,那麼您就贏了。如果你使用了new Foo[],那麼數組的類型是固定的,不管它實際擁有的對象的類型如何。

+0

這是一個有趣的事實。不幸的是在這種情況下,我覺得coverting使用新的T []將是困難的,因爲在創建別的地方是什麼都不知道的更多派生類型:( – Martin 2011-04-25 02:25:07

0

我沒有試過,但它應該工作:

T[] array = Array.ConvertAll<Foo, T>(input, 
    delegate(Foo obj) 
    { 
     return (T)obj; 
    }); 

你可以找到更多的http://msdn.microsoft.com/en-us/library/exc45z53(v=VS.85).aspx

我覺得這個轉換原地的,所以它不會做任何重新-allocations。

+0

不幸的是,從文檔看起來它並不隱蔽在:( – Martin 2011-04-25 02:22:09

0

從我所瞭解的情況中,使用System.Array代替更具體的數組可以幫助您。請記住,Array是所有強類型數組的基類,因此Array引用基本上可以存儲任何數組。你應該讓你的(通用?)字典地圖Type -> Array所以你可以存儲任何強類型數組,而不必擔心需要將一個數組轉換爲另一個數組,現在只需要進行類型轉換。

Dictionary<Type, Array> myDict = ...; 
Array GetFoos(Type t) 
{ 
    // do checks, blah blah blah 
    return myDict[t]; 
} 
// and a generic helper 
T[] GetFoos<T>() where T: Foo 
{ 
    return (T[])GetFoos(typeof(T)); 
} 

// then accesses all need casts to the specific type 
Foo[] f = (Foo[])GetFoos(typeof(Foo)); 
DerivedFoo[] df = (DerivedFoo[])GetFoos(typeof(DerivedFoo)); 
// or with the generic helper 
AnotherDerivedFoo[] adf = GetFoos<AnotherDerivedFoo>(); 
// etc... 

附註,您提供的節目陣列是如何協變的MSDN鏈接。也就是說,您可以將一個更多派生類型的數組存儲在對基類型數組的引用中。你想在這裏實現的是反變換(即,使用基類型的數組來代替更多派生類型的數組),這是另一種方式,以及在沒有進行轉換的情況下哪些數組無法做到。