Avatar billede prec Nybegynder
04. januar 2005 - 15:15 Der er 10 kommentarer og
1 løsning

Min collection laver referencer

Jeg er ved at lave et program der bruger en masse collections som den looper, jeg er dog stødt på et rigtig irriterende problem med dette.
Jeg har et object som jeg ska sætte ned i 2 forskellige collections, først sætter jeg den ind i den ene, ingen problemer... derefter ændrer jeg objektet, og indsætter det nu i den anden, men de ændringer jeg lavede er gået ud over objektet i begge collections... det er som om den laver en reference til objektet, jeg ved ikke om det er en bug eller om det er meningen, men jeg vil gerne undgå denne opførsel.

Jeg har lavet et test project for at vise hvad jeg mener:

namespace ConsoleApplication1
{
    public class test
    {
        public test()
        {
            testobj test1 = new testobj();
            testobj test2 = new testobj();

            testobj2 t = new testobj2();
            t.ABC = "hej";

            test1.Add(t);

            t.ABC = "dav";

            test2.Add(t);

            foreach (testobj2 ss in test1)
            {
                Console.WriteLine(ss.ABC);
            }

            foreach (testobj2 ss in test2)
            {
                Console.WriteLine(ss.ABC);
            }

            Console.ReadLine();
        }
    }

    public class testobj : ICollection
    {
        private testobj2[] items = new testobj2[0];

        public testobj2 this[int i]
        {
            get
            {
                return items[i];
            }
            set
            {
                items[i] = value;
            }
        }

        public void Add(testobj2 s)
        {
            testobj2[] NewArray = new testobj2[items.Length + 1];
            items.CopyTo(NewArray, 0);
            NewArray[items.Length] = s;
            items = NewArray;
        }

        #region ICollection Members

        public void CopyTo(Array array, int index)
        {
            items.CopyTo(array, index);
        }
        public int Count
        {
            get { return items.Length; }
        }

        public bool IsSynchronized
        {
            get { return items.IsSynchronized; }
        }

        public object SyncRoot
        {
            get { return items.SyncRoot; }
        }


        #endregion

        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            return items.GetEnumerator();
        }

        #endregion
    }

    public class testobj2
    {
        private string abc = "";

        public string ABC
        {
            get
            {
                return abc;
            }
            set
            {
                abc = value;
            }
        }
    }
}

OUTPUT:
dav
dav
Avatar billede arne_v Ekspert
04. januar 2005 - 15:19 #1
Sådan virker C#.

Du indsætter en reference til et objekt.

Hvis du vil have en kopi bruger du Clone metoden til at lave en.
Avatar billede prec Nybegynder
04. januar 2005 - 15:21 #2
Kan du forklare mig hvordan jeg sætter det ind i denne sammenhæng, for jeg kan kun finde clone funktionen på arrays
Avatar billede arne_v Ekspert
04. januar 2005 - 15:24 #3
Hvis objektet er cloneable, så kan du bare:

X kopi = (X)original.Clone();

Hvis ikke så må du gøre det cloneable d.v.s. arve fra ICloneable og implementere
en Clone metode,
Avatar billede arne_v Ekspert
04. januar 2005 - 15:26 #4
using System;
using System.Text;

class MainClass
{
    public static void Main(string[] args)
    {
        StringBuilder[] sb1 = { new StringBuilder("a"),
                                new StringBuilder("bb"),
                                new StringBuilder("ccc") };
        StringBuilder[] sb2 = (StringBuilder[])sb1.Clone();
        StringBuilder[] sb3 = new StringBuilder[sb1.Length];
        for(int i = 0; i < sb3.Length; i++)
        {
            sb3[i] = new StringBuilder(sb1[i].ToString());
        }
        sb1[1].Append("x");
        Console.WriteLine(sb1[1] + " " + sb2[1] + " " + sb3[1]);
    }
}
Avatar billede prec Nybegynder
04. januar 2005 - 15:31 #5
Jeg har fundet logikken i det nu, smid et svar hvis du vil
Avatar billede arne_v Ekspert
04. januar 2005 - 15:36 #6
ok
Avatar billede prec Nybegynder
04. januar 2005 - 15:53 #7
Hmm, nu har jeg lavet mit object cloneable og implementeret Memberwiseclone tingen.

                // Her er værdien jeg bruger i seg = ""
                checksegments.Add((Segment)seg.Clone());

                foreach (QueryAction qa in qacs[key])
                {
                    if(qa.InsertValue != null)
                        seg = SetComponent(seg, qa.EDI_ComponentID, FormatString(qa.InsertValue.ToString().Trim()));
                }
                // Her er værdien i både checksegment og seg = "20041210"

Burde den ikke være "" i checksegment ?
Avatar billede prec Nybegynder
04. januar 2005 - 15:56 #8
Jeg har på fornemmeren at det er pga den værdi jeg henter i Segment objektet egentlig ligger i et andet objekt under Segment, som ikke er clonet... Hvis jeg også gør dette objekt cloneable, burde det så virke ?
Avatar billede arne_v Ekspert
04. januar 2005 - 16:36 #9
Man skelner mellem det man kalder "deep clone" og "shallow clone".

deep clone = clone alle under objekter + under under objekter + ...

shallow clone = kopiere alle referencer

MemberwiseClone er det sidste.

Det lyder som du har brug for en deep clone.
Avatar billede prec Nybegynder
04. januar 2005 - 16:48 #10
Jeg er ved at kigge på det, er der nogen nemmere måde at gøre det på end at serialize og deserialize igen ?
Avatar billede arne_v Ekspert
04. januar 2005 - 19:06 #11
Lad alle klasserne have en Clone som kalder Clone på alle members.

Mere kode en serialize + deserialize men pænere.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester