2017-02-23 72 views
1

的類陣列採用這種answer問題「How to add a string to a string[] array? There's no .Add function」我試圖用this answer編寫一個通用的擴展附加元素添加到generic array。僅使用Array.Resize()方法效果好,下面的示例中增加了一個額外的元素,以我的string arrayC#添加擴展Append方法將T型

string[] array = new string[] { "Foo", "Bar" }; 
Array.Resize(ref array, array.Length + 1); 
array[array.Length - 1] = "Baz"; 

但是,當我嘗試使用下面介紹的ArrayExtension方法,調整方法在我的陣列的方法,但是當它返回的數組是不變的?

我的擴展類

public static class ArrayExtensions 
{ 
    public static void Append<T>(this T[] array, T append) 
    { 
     Array.Resize(ref array, array.Length + 1); 
     array[array.Length - 1] = append; // < Adds an extra element to my array 
    } 
} 

使用如下

string[] array = new string[] { "Foo", "Bar" }; 
array.Append("Baz"); 

當該方法返回,所添加的元素不存在。我錯過了什麼?

UPDATE

正如指出的那樣,這個問題已經被問和之前在這裏找到答案。我將接受上一個問題「Changing size of array in extension method does not work?」作爲我的問題的答案。

更新2

,因爲如果在擴展方法用於返回方法它不違反該追加()來修改對象本身,我做了一些改動框架類似的類的預期行爲擴展方法來防止它被錯誤地使用。感謝@NineBerry指出這一點。

我還添加了params T[] add以允許一次添加多個元素。

public static class ArrayExtensions 
{ 
    /// <summary> 
    /// Creates a copy of an object array and adds the extra elements to the created copy 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="array"></param> 
    /// <param name="add">Elemet to add to the created copy</param> 
    /// <returns></returns> 
    public static T[] CopyAddElements<T>(this T[] array, params T[] add) 
    { 
     for (int i = 0; i < add.Length; i++) 
     { 
      Array.Resize(ref array, array.Length + 1); 
      array[array.Length - 1] = add[i]; 
     } 
     return array; 
    } 
} 

用法

string[] array = new string[] { "Foo", "Bar" }; 
array = array.CopyAddElements("Baz", "Foobar"); 
for (int i = 0; i < array.Length; i++) 
{ 
    System.Console.Write($"{array[i]} "); 
} 

/* Output 
* Foo Bar Baz Foobar 
*/ 
+0

Array.Resize是一種欺騙。這實際上是一個新對象的副本。從那裏,你需要一個ref參數對實際參數產生影響。 –

回答

4

Array.Resize創建新的數組。這就是爲什麼你必須使用ref關鍵字將數組傳遞給Array.Resize。因此,從Array.Resize返回後,變量array引用了另一個對象。

沒有辦法使用擴展方法來做你正在做的事情。

爲什麼不簡單地使用列表<>而不是數組?使用Array.Resize是非常昂貴的操作。它意味着每次調用新數組時,都會分配新內存並將數據從舊數組複製到新數組,以增加數組長度。

+0

請提出'列表'您的答案的第一句話。這是真正的解決方案。 –

2

與您的直覺相反,this參數未通過隱含的ref傳遞,也不允許向其添加ref。又見討論here

4

實際情況是什麼

array.Append("Baz"); 

被翻譯成

ArrayExtensions.Append(array, "Baz"); 

這意味着參考array傳遞,所以Append方法內您可以使用參考文獻的副本。然後Array.Resize方法將這個新變量作爲ref,在內存中創建一個新陣列並將變量更改爲指向它。不幸的是,這個只改變了這個變量而不是原來的那個

您可以返回新創建的數組作爲返回值,或者創建一個使用ref而不是擴展方法的靜態方法。