kopiowanie obiektu zamiast tworzenia referencji

2

Cześć,

potrzebuję skopiować obiekt, zamiast tworzyć jego referencji.
Znalazłem taki kod (http://www.codeproject.com/Articles/23832/Implementing-Deep-Cloning-via-Serializing-objects), jednak mam problem z jego użyciem.

Sam kod implementuje:

public static T Clone<T>(T source)

jednak takie użycie nie jest prawidłowe:

bestRowInTS = ObjectCopier<SummaryRow>(currentBestInCompFile.BestSR);

gdzie SummaryRow to moja klasa, bestRowInTS oraz currentBestInCompFile.BestSR są typu SummaryRow.

Pojawia się błąd, informujący o nieprawidłowym użyciu ObjectCopier:

The non-generic type 'MojProgram.ObjectCopier' cannot be used with type arguments

W jaki sposób mogę skopiować obiekt, zamiast tworzyć jego referencję? Pomysł z serializacją (czyli powyższy ObjectCopier) wydał mi się dość dobry, ponieważ można go szybko zaimplementować (choć nie potrafię go jeszcze użyć), a jeśli performance okaże się zbyt kiepski, zawsze będę mógł w przyszłości rozważyć jakąś inną metodę.

Pozdrawiam!

2

Spróbuj tak:

public class SummaryRow : ICloneable
{
    public int JakasWlasciwosc { get; set; }
        
        
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

i użycie:

class Program
{
    static void Main(string[] args)
    {
        SummaryRow bestSR = new SummaryRow();
        bestSR.JakasWlasciwosc = 1;

        SummaryRow bestRowInTS = bestSR.Clone() as SummaryRow;
        bestRowInTS.JakasWlasciwosc = 2;

        Console.WriteLine("bestSR.JakasWlasciwosc = {0}, bestRowInTS.JakasWlasciwosc = {1}", bestSR.JakasWlasciwosc, bestRowInTS.JakasWlasciwosc);
    }
}
1

Nie wiem jak wygląda obiekt, ale na starcie bym się upewnił czy zamiana klasy na strukturę nie rozwiąże problemu. :)

1

Cześć,

niestety to rozwiązanie nie pomogło. Kod jest taki (w uproszczeniu):

SummaryRow bestRowInTS = new SummaryRow();
//...
foreach (BestSRsForDir currentBestInCompFile in bestSRsForDir)
{
	if (bestRowInTSInitialized == false)
	{ // Assign current values to bestRowInTS
		//bestRowInTS = currentBestInCompFile.BestSR; // it does not copy, it only references
		//bestRowInTS = ObjectCopier<SummaryRow>(currentBestInCompFile.BestSR); // not working way
		//bestRowInTS = new SummaryRow(currentBestInCompFile.BestSR);
		bestRowInTS = currentBestInCompFile.BestSR.Clone() as SummaryRow;
	}
	else
	{ // Update current values to bestRowInTS
		if (currentBestInCompFile.BestSR.Profit > bestRowInTS.Profit)
			//bestRowInTS = currentBestInCompFile.BestSR;
			//bestRowInTS = new SummaryRow(currentBestInCompFile.BestSR);
			bestRowInTS = currentBestInCompFile.BestSR.Clone() as SummaryRow;
	}
}

Kiedy jestem wewnątrz 'foreach' to bestRowInTS jest prawidłowo aktualizowane. Kiedy jednak wyjdę poza 'foreach' to bestRowInTS ma same zera i null (za wyjątkiem wartości przypisanych tam, gdzie w kodzie mam "..."). (Jeszcze upewniam się, czy nie ma błędu w moim kodzie, bo może rozwiązanie działa, a błąd jest gdzie indziej).

Próbowałem jeszcze czegoś innego (ostatnia z zakomentowanych linijek), czyli konstruktora kopiującego. Znów to samo (new jest używane wewnątrz 'foreach', zatem obiekt jest lokalny).

Pozdrawiam :)

0

potrzebuję skopiować obiekt, zamiast tworzyć jego referencji.

To nie C++ z manią tworzenia konstruktorów kopiujących, przesuwających, operatorów przypisania i przesunięcia,
w C# obiektów się albo nie kopiuje albo robi się jako struct ;)

[nigdy nie miałem potrzeby użycia ICloneable...]

0

Zmieniło się może coś w .Net? Mam potrzebę skopiowania obiektu kilka razy (klasa z danymi) ale zamiast kopii tworzą se referencje. Ułatwiło by mi to trochę.

0

@.Al, ale co się ma zmienić? Programy nadal działają tak, jak wynika z zapisanych w nich instrukcji. Przypisanie referencji to przypisanie referencji, a klonowanie obiektu to klonowanie obiektu. Trzeba to jakoś zaimplementować - można "ręcznie" pole po polu, serializacją binarną w pamięci albo refleksją. Można też ściągnąć i wykorzystać do tego jakoś bibliotekę.

0

dużo się mogło zmienić, mogli dodać jakąś metodę do klonowania w .net :)

using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(ms, other);
                ms.Position = 0;
                return (T)formatter.Deserialize(ms);
            }

Próbowałem też i tak, ale za dużo błędów (nie oznaczony [Serializable]). Poszukam jeszcze czegoś.

http://www.c-sharpcorner.com/uploadfile/ff2f08/deep-copy-of-object-in-c-sharp/

0

No tak, bo do serializacji binarnej wszystko musi być serializowane. Bezpieczniej refleksją (ale też znacznie wolniej). A tak w ogóle, to co to za obiekty i czemu chcesz je klonować? Może problem jest w pomyśle albo projekcie?

0

Tu masz odpowiedź, dlaczego Ci nie działa to foreach:
http://stackoverflow.com/questions/17676974/changing-objects-value-in-foreach-loop

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.