2012-05-24 12 views
6

Przekazuję listę typu double [] do funkcji w klasie, edytując wartości w ramach funkcji za pomocą zmiennej tempList, a następnie zwracając edytowane wartości. Ale przekazywanie oryginału jest również edytowane i nie chcę, aby były edytowane, aby pasowały do ​​listy podręcznej.Problem z listą edycji <double[]> w C#

Oto kod.

List<double[]> newList = new List<double[](); 
newList = myClass.myFunction(value, originalList); 

// myClass 
... 

// myFunction 
public List<double[]> myFunction(int value, List<double[]> myList) 
{ 
    List<double[]> tempList = new List<double[]>(); 
    for (int i = 0; i < myList).Count; i++) 
    { 
     tempList.Add(myList[i]); 
    } 


    // Do stuff to edit tempList 

    return tempList; 
} 
+0

Co jest faktycznie Twoje pytanie, co chcesz zrobić? Możesz edytować oryginalną listę , nie musisz tworzyć nowej. –

Odpowiedz

4

Należy pamiętać, że tablice są referencyjne typy. Po dodaniu tablicy do tempList dodawane jest tylko odniesienie do tablicy, dzięki czemu zarówno obiekty, jak i obiekty myList i odnoszą się do tych samych obiektów.

Zamiast tego trzeba dokonać klonem tablic:

for (int i = 0; i < myList.Count; i++) 
{ 
    tempList.Add((double[])myList[i].Clone()); 
} 
+0

Tak, ale kod wygląda na podejrzanego. Klonowanie tablicy rzadko jest słuszne. –

0

Problem masz to double[] jest typem odwołania, a nie typ wartości, więc podczas dodawania go do tempList, dodajesz odwołanie do oryginalnego obiektu, a nie do nowego obiektu. Przed dodaniem do tempList musisz utworzyć nowy , aby nie pracował nad oryginalnym obiektem.

Zakładając, że możesz używać LINQ, nie musisz pętli. Możesz zrobić coś takiego:

var tempList = myList.Select(x => x.ToArray()).ToList(); 
0

Dzieje się tak dlatego, że typy kolekcji/odniesienia są przekazywane przez odniesienie. (W rzeczywistości zmienna holdingu jest przekazywana przez wartość, ale wszystkie zmienne wskazują na to samo odniesienie).

Dla wyjaśnienia szczegółów, przeczytaj this SO Answer

Jeśli chcesz, aby zmiany w mojej funkcji nie odzwierciedla w oryginalnej kolekcji, trzeba skopiować/sklonować go, a następnie przejść do myFunction.

Przykład

newList = myClass.myFunction(value, (List<double>)originalList.Clone()); 
1

tablicą here double[] jest rodzajem odniesienia, tak, aby linia

tempList.Add(myList[i]); 

dodaje odniesienie do oryginalnej macierzy. Następnie podczas edytowania tempList edytujesz oryginalną tablicę. Wykonaj kopię tak:

tempList.Add(myList[i].ToArray()); 
0
tempList.Add(myList[i]); 

oznacza, że ​​należy dodać odniesienie do podwójnego [] obiektu na indeksie i notować temp. dlatego, jeśli edytujesz wartość tego obiektu, dostaniesz szansę na obie listy.

jeśli chcesz mieć inny sklonowanych list, które nie wpływają na siebie wzajemnie trzeba będzie zrobić:

List<double[]> tempList = new List<double[]>(); 
for (int i = 0; i < myList).Count; i++) 
{ 
    double[] originalListItem = myList[i]; 

    // the most important step here!!! - clone the originalListItem to clonedListItem 

    tempList.Add(clonedListItem); 
} 


// Do stuff to edit tempList 

return tempList; 
1

dodajesz odniesienie do tablicy do nowej listy, ale nie czyni kopia zawartości każdej tablicy.Twoja kopia powinna wyglądać mniej więcej tak:

foreach (double[] item in myList) 
{ 
    double[] copy = new double[item.Length]; 
    Array.Copy(item, copy); 
    templist.Add(copy); 
} 
0

Kopiujesz podwójne odniesienie [] do nowej listy, jest to płytka kopia. Potrzebna jest głęboka kopia i tworzenie nowych podwójnych tablic do edycji macierzy tymczasowych bez zmiany oryginalnych tablic.

0

Wstawiasz odniesienia do tablicy w tempList, a nie do kopii tablicy. Więc jeśli zmienisz wartość w tempList, zmieniasz oryginalną tablicę.

Ten kod będzie działać lepiej:

for (int i = 0; i < myList.Count; i++) 
    { 
     var copy = new Double[myList[i].Length]; 
     Array.Copy(myList[i], copy, myList[i].Length); 
     tempList.Add(copy); 
    }