Autor Wątek: Kopiowanie klasy  (Przeczytany 3027 razy)

Offline KrystianD

  • Użytkownik
    • http://krystiand.net

# Luty 10, 2006, 13:36:45
w c# klasy są typami referencyjnymi a więc przekazywanie ich jest przekazywaniem referencji:
MojaKlasa kl=new MojaKlasa();
MojaKlasa kl2=kl;
w tym wypadku przy zmianie danych w kl2 zmieniają sie też w klasie kl. jak temu zapobiec??

I jeszcze taka sprawa: w jaki sposób przeekonwertować klasę na byte[]??Chodzi mi o tylko i wyłącznie dane klasy, bo serialize dołącza jakieś info o culture, nazwa programu, nazwa zmiennych.....

Chciałem to zrobć za pomocą Marshal.Copy ale tam trzeba mieć IntPtr, a Marshal.StructureToPtr zwraca wskaźnik tylko na struktury.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Kamil Trzciński

  • Użytkownik

# Luty 10, 2006, 14:44:04
dodaj interfejs ICloneable i zaimplementuj metode Clone, w tej metodzie utworzysz nowa instancje klasy kopiujac wszystkie jej istotne wartosci. Nie ma mozliwosci zamiany klasy na byte[], zostaje ci reczna serializacja wszystkich pol klasy do strumienia tekstowego albo binarnego.

Offline counterClockWise

  • Użytkownik

# Luty 10, 2006, 15:35:44
Heh, takie przypisanie to przecież tylko przypisanie referencji.
Oczywiście potem operując czy to na k1 czy k2 operujesz na tym samym obiekcie.

Overridując clone interfejsu IClonable też musisz uważać, by nie stworzyć sztywnej kopii i nie powtórzyć problemu.



Co do serializacji - jeżeli zależy Ci wyłącznie na zapisywaniu zestawu twoich obiektów na dysku fizycznym to serializacja jest bardzo wygodna. Wystarczy poprzedzić klasę atrybutem [Serializable] i napisać serializacje (dosłownie 5-6 linijek) i deserializacje (doslownie 4-5 linijek) - wszystko bardzo ladnie wytłumaczone w msdn.
« Ostatnia zmiana: Luty 10, 2006, 15:38:33 wysłana przez counterClockWise »

Offline popek007

  • Użytkownik

# Maj 29, 2006, 00:12:10
Na początku klasa która implementuje interfejs IClonable

Klasa ma jedno pole "imie" i jedną metodę "Clone()"
    public class C : ICloneable
    {
        public string imie;

        public object Clone()
        {
            C tmp = new C();
            tmp.imie = this.imie;

            return tmp;
        }
    }
I teraz jak to działa:
            C c1 = new C();
            c1.imie = "Tomek";

            C c2 = (C)c1.Clone();
            c1.imie = "Marcin";
1. Tworzymy sobie obiekt c1 typu C, ustawiamy pole "imie" na "Tomek"
2. KLONUJEMY klase i zapisujemy ja w obiekcie c2

3. Podmiana imienia w c1 (tak aby sprawdzic czy dziala
4. Jak wynikiem bedzie "Tomek" to znaczy ze dziala


Jest to bardzo prosty przyklad zakladajacy ze wiemy jaka klase chcemy klonowac. Generalnie istnieje mozliwosc
automatycznego wykrywania jakie sa pola w klasie i klonowanie ich wtedy implementacja metody Clone() bedzie
bardziej skomplikowana.

Pozdrawiam, Tomek

/// EDIT: NAUCZCIE SIę KORZYSTAć ZE ZNACZNIKÓW W POSTACH!!!!!
« Ostatnia zmiana: Maj 29, 2006, 10:00:25 wysłana przez shyha »

Offline KrystianD

  • Użytkownik
    • http://krystiand.net

# Listopad 19, 2006, 21:36:16
Kiedyś znalazłem jak zamienić klasę na byte[] więc może napisze, tak dla pokoleń  ;D ;D ;D

[StructLayout (LayoutKind.Sequential)]
class CLS
{
[MarshalAs (UnmanagedType.ByValTStr, SizeConst = 10)]
public String s;
public Int32 d;
}
public Form1 ()
{
//Zamiana CLS na Byte[]
CLS c = new CLS ();
c.s = "ab";
c.d = 3;
Byte[] bt = new Byte[Marshal.SizeOf (c)];
IntPtr p = Marshal.AllocHGlobal (Marshal.SizeOf (c));
Marshal.StructureToPtr (c, p, false);
Marshal.Copy (p, bt, 0, Marshal.SizeOf (c));
Marshal.Release (p);

foreach (Byte b in bt)
{
listBox1.Items.Add (b.ToString ());
}

//Zamiana Byte[] na CLS
IntPtr p2 = Marshal.AllocHGlobal (Marshal.SizeOf (c));
Marshal.Copy (bt, 0, p2, Marshal.SizeOf (c));
CLS cc = (CLS)Marshal.PtrToStructure (p2, typeof (CLS));
Marshal.Release (p2);
MessageBox.Show (cc.s.ToString ());
MessageBox.Show (cc.d.ToString ());
}

zmienna Byte[] bt zawiera:
97, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0

Tylko nie wiem dlaczego bajtów jest 16 a powinno być 10 + sizeof(int) czyli 14..... ale mniejsza o to

Offline gamecreator

  • Użytkownik
    • Game C++reator - strona o tworzeniu gier w C++

# Luty 15, 2007, 01:57:08
Cytat: ayufan
dodaj interfejs ICloneable i zaimplementuj metode Clone, w tej metodzie utworzysz nowa instancje klasy kopiujac wszystkie jej istotne wartosci.
Heh.. żeby do zwykłego zrobienia kopii trzeba było kombinować z nadpisywaniem interfejsów w klasach...  ::)  to ja podziękuję i pozostanę przy C++, gdzie kopiowanie mam automatycznie, a jak mi się nie podoba to mogę sobie go dopiero wtedy nadpisywać ;J

Offline Xion

  • Moderator
    • xion.log

# Luty 15, 2007, 18:34:07
Wypada tu tylko zadać proste pytanie: "I co z tego?" W C++ kopiowanie obiektów klas jest automatyczne, bowiem taka jest filozofia tego języka, gdzie klasy jak najbardziej przypominają typy wbudowane. W C++ klasy są więc typami bezpośrednimi.
Natomiast w C# klasy są typami referencyjnymi, zatem przy ich przypisywaniu kopiowane są jedynie referencje do nich. Sklonowanie samego obiektu musi być już jawne. Nie widzę tutaj problemu (a wręcz przeciwnie), bo jeśli kopiowanie jest istotną częścią funkcjonalności danego typu, to zawsze można zdefiniować jako typ bezpośredni - czyli strukturę.