2012-09-24 50 views
4

有沒有在C#的方式做這樣的事情:在運行時創建一個通用的陣列

public void Foo<T>() 
{ 
    T[] arr = Goo() as T[]; 
} 

凡咕返回object[],使用反射或什麼?

+0

我不認爲'object []'可能永遠不是'T []'。一個'對象'可能是。 –

+0

@Damien_The_Unbeliever:[協變和逆變在C#,第二部分:陣列協方差(http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-部分的兩陣列covariance.aspx) – Ani

+0

@Ani - I可以誤讀一點,但它似乎是說,'對象[] A =新T []'將是有效的('其中,T:class'),不另一種方式。 –

回答

4

你可以使用LINQ:

public void Foo<T>() 
{ 
    T[] arr = Goo().OfType<T>().ToArray(); 
} 

在你的榜樣,你是鑄造object[]T[]如果兩個類型完全匹配這也將工作:

public void Foo<T>() 
{ 
    T[] arr = Goo() as T[]; 
    if (arr != null) 
    { 
     // use the array 
    } 
} 

例如這將工作中以下情況:

public object[] Goo() 
{ 
    return new string[] { "a", "b" }; 
} 

然後像這樣調用foo:

Foo<string>(); 
0

也許最簡單,最可靠的方法是將陣列複製,做投項目按項目:

public void Foo<T>() 
{ 
    T[] arr = Array.ConvertAll(Goo(), x => (T)x); 
} 

這是一個「unbox.any」,這意味着(到JIT):

  • 做一個castclass(即參考保留型檢查)如果T原來是引用類型的unbox如果T原來是數值類型的引用類型

數組是協變

  • 做,這意味着T[]可以是,其代表,作爲object[]。正因爲如此,有機會的Goo()結果是實際上是一個T[]。我們可能還需要測試:

    public T[] Foo<T>() 
    { 
        var tmp = Goo(); 
        T[] arr = tmp as T[]; 
        if(arr == null && tmp != null) { 
         arr = Array.ConvertAll(Goo(), x => (T)x); 
        } 
        return arr; 
    } 
    

    一個煩惱這雖然是我們現在有不同的語義 - 在某些情況下,它是在相同的陣列,在某些情況下被複制。如果我們變異了這個數組,這可能會有問題。

  • +1

    嗯......簽名中有'void',但是你返回數組?它不應該有'T []'作爲返回類型嗎? – Noctis

    +0

    @Nocitus yup;編碼在'電話:)上的危險:) –