Bei Methodenüberladung übergebenes Originalarray nicht ändern

  • C#

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von PadreSperanza.

    Bei Methodenüberladung übergebenes Originalarray nicht ändern

    Hallo liebe Community,

    ich lerne gerade C#. Momentan bin ich bei der Methodenüberladung und habe das Problem, dass sich das übergebene Originalarray nach der Übergabe an eine Methode und der Bearbeitung darin ändert, das möchte ich irgendwie umgehen.
    Könnt Ihr mir sagen wie ich das machen muss, in meinen Büchern find ich da leider nichts dazu.

    Hier der Quellcode und vielen Dank.

    C#-Quellcode

    1. public static string[] einfuegenOverload(string[] stringFeld)
    2. {
    3. string[] ergebnis = new string[16];
    4. string[] mystringFeld = stringFeld;
    5. ergebnis = mystringFeld;
    6. ergebnis[0] = "EingefuegterText01";
    7. ergebnis[1] = "EingefuegterText02"; ;
    8. ergebnis[2] = "EingefuegterText03"; ;
    9. ergebnis[3] = "EingefuegterText04"; ;
    10. return ergebnis;
    11. }
    12. public static string[] einfuegenOverload(string[] stringFeld, int pos1)
    13. {
    14. string[] ergebnis = new string[stringFeld.Length];
    15. int position1 = pos1;
    16. string[] mystringFeld = stringFeld;
    17. ergebnis = mystringFeld;
    18. ergebnis[position1] = "EingefuegterText01";
    19. return ergebnis;
    20. }
    21. public static string[] einfuegenOverload(string[] stringFeld, int pos1, int pos2)
    22. {
    23. string[] ergebnis = new string[stringFeld.Length];
    24. int position1 = pos1;
    25. int position2 = pos2;
    26. string[] mystringFeld = stringFeld;
    27. ergebnis = mystringFeld;
    28. ergebnis[position1] = "EingefuegterText01";
    29. ergebnis[position1] = "EingefuegterText02";
    30. return ergebnis;
    31. }
    32. public static string[] einfuegenOverload(string[] stringFeld, int pos1, string[] stringFeld02)
    33. {
    34. string[] ergebnis = new string[stringFeld.Length];
    35. string[] myStringFeld = stringFeld;
    36. string[] myStringFeld02 = stringFeld02;
    37. int position1 = pos1;
    38. ergebnis = myStringFeld;
    39. ergebnis[position1] = "EingefuegterText01";
    40. myStringFeld02.CopyTo(ergebnis, 1);
    41. return ergebnis;
    42. }
    43. string[] stringFeld01 = new string[] { "Tarzan", "Zorro", "BatMan", "Robin", "BatGirl", "Superman", "Black Widdow", "SuperGirl", "Hulk", "The Thing", "Dr. Strange", "Venom", "Black Panther", "She-Ra", "Battle Cat", "Harley Quinn" };
    44. string[] stringFeld02 = new string[] { "Luke Skywalker", "Obi Wan Kenobi", "Han Solo", "C3PO", "R2D2" };
    45. string[] ergebnisOverloading1 = new string[16];
    46. string[] ergebnisOverloading2 = new string[16];
    47. string[] ergebnisOverloading3 = new string[16];
    48. string[] ergebnisOverloading4 = new string[16];
    49. int position1 = 1;
    50. int position2 = 2;
    51. int position3 = 3;
    52. ergebnisOverloading1 = einfuegenOverload(stringFeld01);
    53. ergebnisOverloading2 = einfuegenOverload(stringFeld01, position1);
    54. ergebnisOverloading3 = einfuegenOverload(stringFeld01, position1, position2);
    55. ergebnisOverloading4 = einfuegenOverload(stringFeld01, position3, stringFeld02);
    56. Console.WriteLine("Ausgabe originale Methode: ");
    57. foreach (string item in ergebnisOverloading1)
    58. {
    59. Console.WriteLine(item);
    60. }
    61. Console.WriteLine();
    62. Console.WriteLine("Ausgabe Überladung 1: ");
    63. foreach (string item in ergebnisOverloading2)
    64. {
    65. Console.WriteLine(item);
    66. }
    67. Console.WriteLine();
    68. Console.WriteLine("Ausgabe Überladung 2: ");
    69. foreach (string item in ergebnisOverloading3)
    70. {
    71. Console.WriteLine(item);
    72. }
    73. Console.WriteLine();
    74. Console.WriteLine("Ausgabe Überladung 4: ");
    75. foreach (string item in ergebnisOverloading4)
    76. {
    77. Console.WriteLine(item);
    78. }
    79. Console.WriteLine();
    @Questioner Willkommen im Forum. :thumbup:
    3 Prozeduren und ein Haufen Zeilen ohne Prozedurrahmen.
    Was müssen wir tun, um Deinen Effekt zu reproduzieren?
    ====
    Sieh Dir Prozedur einfuegenOverload(string[] stringFeld) an, da wird auf der Instanz des Eingabefeldes gearbeitet, Du änderst die Elemente.
    Die Instanz des Feldes selbst wird nicht geändert.
    Setz einen Haltepunkt drauf, steppe Dein Programm zeilenweise durch und sieh Dir den Inhalt des Arrays an.
    Debuggen, Fehler finden und beseitigen

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Questioner
    Prozedur public static string[] einfuegenOverload(string[] stringFeld)

    C#-Quellcode

    1. string[] ergebnis = new string[16]; // es wird ein neues Array angelegt, die Zuweisung ist obsolete
    2. string[] mystringFeld = stringFeld; // es wird eine Kopie der Instanz des Parameters erzeugt
    3. ergebnis = mystringFeld; // das neue Array wird mit der Kopie der Instanz des Parameters überschrieben
    4. ergebnis[0] = "EingefuegterText01"; // die ersten 4 Member der Instanz des Parameters werden überschrieben
    5. ergebnis[1] = "EingefuegterText02"; ;
    6. ergebnis[2] = "EingefuegterText03"; ;
    7. ergebnis[3] = "EingefuegterText04"; ;
    8. return ergebnis;
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    Deine Kommentare habe ich verstanden, auch dass das Zuweisung Anlegen des neuen Arrays obsolet ist.
    Aber ich komm einfach nicht auf die Lösung.
    Ich geb dich das Array ergebnis zurück und speichere es in einem Array das den Rückgabewert speichert.
    Ich kriegs einfach nicht hin dass das Originalarray das ich vor dem Aufruf der Funktion erstelle unangetastet bleibt.

    Kannst Du mir nicht einfach die Lösung posten ich versuchs schon seit Stunden.
    Ich hab schon om Netz was gefunden Thema save, unsave und Pointer.
    Gibt es da nicht einen Mechanismus von C# ohne das Pointern?
    @Questioner Du musst das Wesen von Instanzen verstehen.
    Probier mal dies:

    C#-Quellcode

    1. public static string[] einfuegenOverload(string[] stringFeld)
    2. {
    3. string[] ergebnis = new string[stringFeld.Length];
    4. Array.Copy(stringFeld, ergebnis, stringFeld.Length);
    5. //string[] mystringFeld = stringFeld;
    6. //ergebnis = mystringFeld;
    7. ergebnis[0] = "EingefuegterText01";
    8. ergebnis[1] = "EingefuegterText02"; ;
    9. ergebnis[2] = "EingefuegterText03"; ;
    10. ergebnis[3] = "EingefuegterText04"; ;
    11. return ergebnis;
    12. }
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    "Gib einem Mann einen Fisch und du ernährst ihn für einen Tag. Lehre einen Mann zu fischen und du ernährst ihn für sein Leben."

    Wie debugge ich richtig? => Debuggen, Fehler finden und beseitigen
    Wie man VisualStudio nutzt? => VisualStudio richtig nutzen
    Mit diesen Problemen wirst du noch häufiger zu kämpfen haben, gerade bei Kopien ist es wichtig zu wissen, was man genau macht - Stichwort flache Kopien und tiefe Kopien.

    Was dir für die Lösung gefehlt haben dürfte, ist der Hinweis, dass "Strings" sich zwar wie Werte-Typen (vgl. mrMo-Beitrag) verwenden lassen, aber eigentlich Referenztypen sind (quasi Objekte).

    Bei Wertetypen sieht der Sachverhalt wie folgt aus:

    C#-Quellcode

    1. int a;
    2. int b;
    3. a = 15;
    4. b = 21;
    5. a = b; // hier wird der Variablen a der Wert von b zugewiesen. a hat also den Wert 21. Und hier wird tatsächlich der wert 21 in die Variable a geschrieben. Beide haben nun 21.
    6. b = 0;

    Wenn du dir hiernach a und b anschaust, wirst du feststellen, dass a und b unterschiedliche Werte enthalten, da es Wertetypen sind.

    Wenn du Referenz-(Objekt-)Typen hast, sieht der Sachverhalt anders aus, da Referenztypen auf einem anderen Speicherbereich liegen. Wenn du einer Variablen einen Referenztyp zuweist, dann besitzt die Variable nicht den eigentlichen "Wert" dieses Objekts, sondern einen sogenannten Zeiger (pointer) auf den Speicherbereich, wo sich das Objekt eigentlich befindet (Stichwort Heap-Speicher). Denn das Objekt kann ja belieb groß oder komplex sein und auch selbst weitere Variablen etc. besitzen.

    Stell dir folgenden Code vor:

    C#-Quellcode

    1. Auto autoA = new Auto();
    2. Auto autoB = autoA;


    Wir haben ein neues Auto, das wird in autoA gespeichert. Danach wird autoB autoA zugewiesen. Der Unterschied zu oben besteht darin, dass du nicht einfach das Auto kopierst und in autoB packst, sondern du musst dir vorstellen, dass beide (autoA und autoB) exakt dasselbe Auto meinen und referenzieren (deshalb Referenztyp). Du könntest dir also vorstellen, dass autoA und autoB beide mit demselben Auto unterwegs sind. Wenn also autoA das Auto um 50km bewegt hat und du fragst dann bei autoB nach, dann ist dort das Auto auch 50km weiter gefahren, da autoB dasselbe Auto wie autoA sieht. Beide Variablen verweisen hierbei auf dieselbe Instanz Auto auf dem Heap-Speicher.
    Um hier eine eigene - neue Instanz zu bekommen, die von der anderen getrennt ist, musst du das Schlüsselwort ​new verwenden. Das sagt eigentlich sehr gut aus, dass hier auch wirklich eine neue Instanz geschaffen wird, die du unabhängig von der anderen verwenden kannst. Solange du das Schlüsselwort new nicht verwendest, sind Referenztypen immer exakt dieselben Objekte und können von mehreren Variablen (hier im Beispiel also Insassen des Autos) zeitgleich bedient werden.

    Beim Kopieren von Werte-Typen werden direkt ihre Werte kopiert. Beim Kopieren von Referenz-Typen wird nicht das eigentliche Objekt kopiert, sondern lediglich der Zeiger auf das Objekt. Also am Beispiel Auto, wenn autoA und autoB Erwachsene wären, dann kannst du dir das so vorstellen:


    ​Auto autoA = new Auto(); Dem Erwachsenen, den wir mit autoA ansprechen, bekommt das nagelneue Auto gezeigt und steigt ein.
    ​Auto autoB = autoA Dem Erwachsenen B wird dasselbe Auto gezeigt, indem Erwachsener A noch sitzt und B seigt ebenfalls ein. Nun sitzen also beide in demselben Auto und beide können mit ihm interagieren.

    Und wenn sie nun voneinander ein jeweils eigenes Auto haben sollen, brauchst du auch zweimal ​new.

    Und nun auch nochmal bezogen auf deinen Post: Anhand dieser Zeile erkennst du, dass es hier ein Referenztyp ist:

    C#-Quellcode

    1. ​string[] ergebnis = new string[16];