[C#] Arrays

Pagina: 1
Acties:

  • Defector
  • Registratie: December 2005
  • Niet online
Ik snap niet helemaal hoe c# met arrays werkt. Ik weet wat reference types en value types zijn. Maar ik weet nog niet goed hoe ik er mee om moet gaan. Hoe kan ik bijvoorbeeld een array doorgeven aan een methode zonder dat ik een reference heb naar het origineel dus dat de veranderingen die ik maak in de methode niet terug komen in de originele array of andersom.

Ik heb heel veel tutorials gelezen over c# en daar wordt het verschil tussen reference types en value types goed uitgelegd maar niet hoe je er dan mee kunt werken. Of iig niet op een manier dat ik het snap.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Defector schreef op zaterdag 28 april 2007 @ 16:18:
Hoe kan ik bijvoorbeeld een array doorgeven aan een methode zonder dat ik een reference heb naar het origineel dus dat de veranderingen die ik maak in de methode niet terug komen in de originele array of andersom.
De array kopieren natuurlijk :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Defector
  • Registratie: December 2005
  • Niet online
tuurlijk dat ik daar niet aangedacht heb :S

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Een array is een object, geen value type. Dus als jij een array meegeeft aan een method, dan geef je dus een reference door naar dat array en de method kan dus in jouw array kloten.

Als je dit niet wilt, dan moet je een copy / clone maken van je array. Dit houdt in feite in dat indien het een array van valuetypes is (int, bool etc. GEEN String!) je een nieuw array krijgt en copieen van die values in je nieuwe array. Is het een array van reference types dan krijg je een nieuw array met daarin references naar DEZELFDE objects. Een copy maak je door de Clone method aan te roepen van je array.

Ik weet niet precies in welke situatie je dit wilt gebruiken, dus als je wat meer context zou kunnen geven zou dat wenselijk zijn.

Met value types werken (dus ook structs) houdt in dat je met niet muteerbare values werkt. Reference types zijn gewone 'objects' dus een object met properties die je kunt aanpassen en methods die je kunt aanroepen.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • Defector
  • Registratie: December 2005
  • Niet online
Ik heb een xml bestand en daar lees ik een aantal dingen uit en die komen in een array. Die array wil ik in een object stoppen waar ik later mee werk. Dit heb ik allemaal al gemaakt maar ik kwam erachter dat de waardes van de array steeds veranderde. Daar ben ik nu achter dat het kwam omdat ik een reference doorgaf dus inprincipe steeds met dezelfde array aan het werk was.

Zoals ik het nu begrijp moet ik als ik dat niet wil de waarden van de array kopiëren naar een nieuwe array. Maar hoe zit het dan met de string array die ik nu heb want dat zijn toch ook references ? Dus dan zou ik alsnog met de met dezelfde strings bezig zijn. Of zie ik dat verkeerd ?

[ Voor 0% gewijzigd door Defector op 28-04-2007 17:05 . Reden: typfaut ]


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Met strings juist niet. String zijn Immutable, wat dus inhoud dat je een string niet kan veranderen. Op het moment dat je een array element wat een string is wilt veranderen zal er eigenlijk een nieuwe string gemaakt worden en die zal dan in de array toegewezen worden.

Als je het over andere objecten hebt dan kan dat inderdaad wel gebeuren.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Verwijderd

@rwb: Dat gaat niet helemaal op voor arrays/lists. Het is een combinatie van jouw antwoord + bovenstaande antwoorden. Zie dit voorbeeld:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] list = new string[2];
            list[0] = "a";
            list[1] = "b";
            Console.WriteLine("Original array:");
            DisplayArray(list);

            Console.WriteLine("Change array:");
            DoSomethingWithArray(list);

            Console.WriteLine("Original array (again):");
            DisplayArray(list);

            Console.WriteLine("============");
            Console.WriteLine("Another array test:");
            list[0] = "a";

            Console.WriteLine("Original array:");
            DisplayArray(list);

            Console.WriteLine("Clone array and change it:");
            DoSomethingWithArray(((string[])list.Clone()));

            Console.WriteLine("Original array:");
            DisplayArray(list);

            Console.WriteLine("============");

            string test = "test";
            DisplayString(test);

            DoSomethingWithString(test);

            DisplayString(test);

            Console.Read();

        }

        static void DoSomethingWithString(string text)
        {
            text = "test changed";
            DisplayString(text);
        }

        static void DoSomethingWithArray(string[] array)
        {
            array[0] = "c";
            DisplayArray(array);
        }

        static void DisplayString(string text)
        {
            Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Text: {0}", text));
        }

        static void DisplayArray(string[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                Console.WriteLine(string.Format(CultureInfo.InvariantCulture,"{0}: {1}",i,array[i]));
            }
        }
    }
}

[ Voor 17% gewijzigd door Verwijderd op 28-04-2007 19:44 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op zaterdag 28 april 2007 @ 19:39:
@rwb: Dat gaat niet helemaal op voor arrays/lists
rwb beweert ook niet anders, hij zegt dat als je een array van strings kopieert dat een deep copy niet nodig is omdat je de strings toch niet kunt wijzigen. Daarom is het niet erg dat 2 verschillende arrays naar dezelfde strings wijzen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op zaterdag 28 april 2007 @ 19:58:
[...]

rwb beweert ook niet anders, hij zegt dat als je een array van strings kopieert dat een deep copy niet nodig is omdat je de strings toch niet kunt wijzigen. Daarom is het niet erg dat 2 verschillende arrays naar dezelfde strings wijzen.
Staat nergens in zijn hele zin ook maar iets over een copy/clone van de array. Wat hij zegt gaat dus alleen op als je een copy/clone (Ligt maar aan de MS implemenatie in die betreffende class) van de array doet (zie voorbeeld, idd geen deep copy) zoals jij wel aan geeft.

In mijn voorbeeld zie je dus twee situaties met en zonder clone. Zonder de clone wordt er dan wel een nieuwe string aan gemaakt, maar die nieuwe reference wordt gewoon vrolijk in de originele array gezet. In het tweede geval wordt er de array gecloned en heb je dus 2 arrays en in de geclonede versie wordt alleen de nieuwe string gezet.

[ Voor 21% gewijzigd door Verwijderd op 28-04-2007 20:26 . Reden: ff meer verduidelijkt ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

't Staat niet in zijn post nee, maar dat was wel de context van de discussie. Even de volledige context quoten dan maar
Defector schreef op zaterdag 28 april 2007 @ 17:04:
Maar hoe zit het dan met de string array die ik nu heb want dat zijn toch ook references ? Dus dan zou ik alsnog met de met dezelfde strings bezig zijn. Of zie ik dat verkeerd ?
rwb schreef op zaterdag 28 april 2007 @ 19:10:
Met strings juist niet. String zijn Immutable, wat dus inhoud dat je een string niet kan veranderen. Op het moment dat je een array element wat een string is wilt veranderen zal er eigenlijk een nieuwe string gemaakt worden en die zal dan in de array toegewezen worden.

Als je het over andere objecten hebt dan kan dat inderdaad wel gebeuren.
Vertaling:
[Defector] als ik een array kopieer en ik werk met de contents van die array (strings dus, wat reference types zijn, dus die nog steeds naar dezelfde objecten wijzen), gaat het dan niet fout?
[rwb] Nee, want strings zijn immutable. Als je een string "aanpast" dan krijg je eigenlijk een referentie naar een nieuwe string

Conclusie: een shallow copy van een array van strings volstaat (Array.Clone() dus)

[ Voor 3% gewijzigd door .oisyn op 28-04-2007 20:41 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

.oisyn schreef op zaterdag 28 april 2007 @ 20:39:
't Staat niet in zijn post nee, maar dat was wel de context van de discussie. Even de volledige context quoten dan maar
[...]


[...]


Vertaling:
[Defector] als ik een array kopieer en ik werk met de contents van die array (strings dus, wat reference types zijn, dus die nog steeds naar dezelfde objecten wijzen), gaat het dan niet fout?
[rwb] Nee, want strings zijn immutable. Als je een string "aanpast" dan krijg je eigenlijk een referentie naar een nieuwe string

Conclusie: een shallow copy van een array van strings volstaat (Array.Clone() dus)
Dat snap ik, alleen werd het in een algemenere context geplaatst die niet in alle situaties op gaat. :P En zeker wanneer iemand zich net echt begint bezig te houden met C# moet je dat wel ff goed verduidelijken ;)

[ Voor 6% gewijzigd door Verwijderd op 28-04-2007 20:57 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 07:20

.oisyn

Moderator Devschuur®

Demotivational Speaker

Agreed :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Je kan hem ook serializen en dan deserializen. Dan heb je zeker een deep copy.

Verwijderd

Verwijderd schreef op zondag 29 april 2007 @ 11:57:
Je kan hem ook serializen en dan deserializen. Dan heb je zeker een deep copy.
Je bent het er wel mee eens hoop ik dat dit een gigantisch omslachtige (foutgevoelige) manier is.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Waarom foutgevoelig?

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:54
waarom omslachtig ?

https://fgheysels.github.io/


  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 01-12 16:44
Sterker nog, .NET doet intern een serialize en deserialize (al dan niet diep) :)

  • EfBe
  • Registratie: Januari 2000
  • Niet online
darkmage schreef op maandag 30 april 2007 @ 09:34:
Sterker nog, .NET doet intern een serialize en deserialize (al dan niet diep) :)
In welke situatie? Array.Clone? Lijkt me niet, want Clone doet een MemberwiseClone wat gewoon een memcpy is

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

Als jij vanuit Den Bosch naar Amsterdam moet. Rijd jij dan via Rotterdam naar Amsterdam, of gewoon rechstreeks via de A2? (Is hetzelfde idee).
Niet elke class heeft een (de)serialize functie (vooral eigen types), die moet je dan dus zelf schrijven. Dat geldt ook voor Clone/Copy methodes, maar het schrijven van een dergelijke functie is eenvoudiger en geldt dat dus in een veel mindere mate. Daarnaast ben jij bij serialisatie bezig met Streams, Readers en Writers.

[ Voor 10% gewijzigd door Verwijderd op 30-04-2007 13:18 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:54
Verwijderd schreef op maandag 30 april 2007 @ 13:13:
[...]

Als jij vanuit Den Bosch naar Amsterdam moet. Rijd jij dan via Rotterdam naar Amsterdam, of gewoon rechstreeks via de A2? (Is hetzelfde idee).
Overtuigend ben je niet. :)
Waarom is serializing / deserializing een 'omweg' om een deep clone te verkrijgen ? Het is makkelijk, onderhoudbaar (als je class aangepast wordt, hoef je je clone method niet aan te passen). Het enige waar je rekening moet mee houden, is dat je types serializable moeten zijn. (Maar da's een kwestie van je class te decoraten met [Serializable]
Niet elke class heeft een (de)serialize functie (vooral eigen types), die moet je dan dus zelf schrijven.
Niks van; je moet enkel het Serializable attribute gebruiken, en dan kan je je class simpel mbhv de standaard Formatter serializen. (En da's eenvoudiger / onderhoudbaarder dan een eigen copy/clone method te schrijven).
Daarnaast ben jij bij serialisatie bezig met Streams, Readers en Writers.
Een memorystream en een BinaryFormatter. Da's al.

https://fgheysels.github.io/


Verwijderd

whoami schreef op maandag 30 april 2007 @ 13:28:
[...]
Overtuigend ben je niet. :)
Waarom is serializing / deserializing een 'omweg' om een deep clone te verkrijgen ? Het is makkelijk, onderhoudbaar (als je class aangepast wordt, hoef je je clone method niet aan te passen). Het enige waar je rekening moet mee houden, is dat je types serializable moeten zijn. (Maar da's een kwestie van je class te decoraten met [Serializable]


[...]
Niks van; je moet enkel het Serializable attribute gebruiken, en dan kan je je class simpel mbhv de standaard Formatter serializen. (En da's eenvoudiger / onderhoudbaarder dan een eigen copy/clone method te schrijven).


[...]
Een memorystream en een BinaryFormatter. Da's al.
Ja, maar die memorystream moet je wel netjes en goed afsluiten (En verbasingwekkend doen dat maar erg weinig mensen). Maar om een object te clonen/copyen wil je hem niet eerst als XML (of wat dan ook) formateren om er vervolgens weer een object van te maken, die middenstap is volstrekt onnodig (Rotterdam dus). En je kunt heel gemakkelijk een paar attributen vergeten.

Ach het is mierengeneuk op een mooie lentedag :P Het is gewoon een keuze die je moet maken :P .

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Verwijderd schreef op maandag 30 april 2007 @ 13:13:
[...]

Als jij vanuit Den Bosch naar Amsterdam moet. Rijd jij dan via Rotterdam naar Amsterdam, of gewoon rechstreeks via de A2? (Is hetzelfde idee).
Nee.
[...]
Niet elke class heeft een (de)serialize functie (vooral eigen types), die moet je dan dus zelf schrijven. Dat geldt ook voor Clone/Copy methodes, maar het schrijven van een dergelijke functie is eenvoudiger en geldt dat dus in een veel mindere mate. Daarnaast ben jij bij serialisatie bezig met Streams, Readers en Writers.
Kost 1 attribute, dus zoveel werk is het niet.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:54
Verwijderd schreef op maandag 30 april 2007 @ 13:33:
[...]


Ja, maar die memorystream moet je wel netjes en goed afsluiten
Your point being ? zo'n moeite is dat toch niet ?
Maar om een object te clonen/copyen wil je hem niet eerst als XML (of wat dan ook) formateren om er vervolgens weer een object van te maken
Tja, da's niet zo lastig/duur. Serializen, deserializen klaar.
Ik zou wel eens willen weten hoe jij op een efficiente en onderhoudbare manier een deep-clone method gaat maken voor een class die nog een aantal associaties / collections heeft.

https://fgheysels.github.io/


Verwijderd

whoami schreef op maandag 30 april 2007 @ 21:02:
[...]
Your point being ? zo'n moeite is dat toch niet ?

[...]
Tja, da's niet zo lastig/duur. Serializen, deserializen klaar.
Ik zou wel eens willen weten hoe jij op een efficiente en onderhoudbare manier een deep-clone method gaat maken voor een class die nog een aantal associaties / collections heeft.
Mwha, ligt er idd heel erg aan. Maar zoals we geloof ik alle 3 al zeiden: Beetje nutteloze discussie. Het kan op beide manieren. Alleen is (de)serialiseren daar niet in eerste instantie voor bedoeld en dat is eigenlijk mijn (enige) echte bezwaar tegen het op die manier doen. Zulke acties veroorzaken tegenwoordig ook al dat gezeik met Windows patches. Microsoft dicht eindelijk een lek, maar een stel bedrijven misbruiken de fout/eigenschap, omdat nu eenmaal zo makkelijk was met alle gevolgen vandien....

[ Voor 13% gewijzigd door Verwijderd op 30-04-2007 21:36 ]


Verwijderd

C#:
1
2
3
4
5
6
7
8
9
10
11
public static T DeepCopy<T>(T t)
{
        using (MemoryStream mStream = new MemoryStream())
        {
            BinaryFormatter oBinaryFormatter = new BinaryFormatter();
            oBinaryFormatter.Serialize(mStream, t);
            mStream.Seek(0, 0);
            T tCopy = (T)oBinaryFormatter.Deserialize(mStream);
            return tCopy;
        }
}
Pagina: 1