Code is modifying the wrong variable… why?

  • A+
Category:Languages

I have a strange thing where some code I am doing is modifying both the copy and the original List.. I have boiled the problem down as much as I can to only show the error in a single file. Though my real world example us a lot more complex.. but at the root of it all this is the problem.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;  namespace TestingRandomShit {     class Program     {         private static string rawInput;         private static List<string> rawList;         private static List<string> modifiedList;          static void Main(string[] args)         {             rawInput = "this is a listing of cats";              rawList = new List<string>();             rawList.Add("this");             rawList.Add("is");             rawList.Add("a");             rawList.Add("listing");             rawList.Add("of");             rawList.Add("cats");              PrintAll();              modifiedList = ModIt(rawList);              Console.WriteLine("/n/n**** Mod List Code has been run **** /n/n");             PrintAll();         }          public static List<string> ModIt(List<string> wordlist)         {              List<string> huh = new List<string>();             huh = wordlist;              for (int i = 0; i < huh.Count; i++)             {                 huh[i] = "wtf?";             }             return huh;         }  //**************************************************************************************************************** //Below is just a print function.. all the action is above this line           public static void PrintAll()         {             Console.WriteLine(": Raw Input :");             Console.WriteLine(rawInput);              if (rawList != null)             {                 Console.WriteLine("/n: Original List :");                 foreach (string line in rawList)                 {                     Console.WriteLine(line);                 }             }              if (modifiedList != null)             {                 Console.WriteLine("/n: Modified List :");                 foreach (string wtf in modifiedList)                 {                     Console.WriteLine(wtf);                 }                 Console.ReadKey();             }         }     } } 

Basically, I have three variables.... a string and two List. The original code dose some tokenisation on the string but for this demo I simple use the List.Add() to fake it to make it simple to read.

So I now have a string and a List with a single word in each element.

This is the confusing part that I do not understand.. I know it has something to do with references but I can not work out how to fit it.

There is a method I have called ModIt()... it simple takes in a List then makes a completely new List called huh, copies the original list over the new list and then changes every line in huh to "wtf?".

Now as I understand it.. I should end up with 3 variables...

1) a string 2) a List with a different word in each element 3) a List of the same length as the other with each element being "wtf?"

But, what happens is that is I try to print out both List they BOTH have every element set to "WTF?".... so yeah.. wtf man? I am super confused. I mean in the ModIt I even build a entire new string rather than modding the one being passes but it doesn't seem to effect anything.

This is the output...

: Raw Input : this is a listing of cats

: Original List : this is a listing of cats

**** Mod List Code has been run ****

: Raw Input : this is a listing of cats

: Original List : wtf? wtf? wtf? wtf? wtf? wtf?

: Modified List : wtf? wtf? wtf? wtf? wtf? wtf?

 


huh = wordlist; doesn't copy the items of wordlist into a new list, it copies the reference to the same object occupied by wordlist (i.e. huh and wordlist then point at the same object in memory).

If you want a copy, the simplest way to produce one is using LINQ:

List<string> huh = wordlist.ToList(); 

Note that this will be a "shallow copy". If your list stores reference objects, both the old and new lists will store references to the same objects.

See here for more reading on value vs reference types, and then here if you need a deep copy.

Since all you're doing is replacing the value at an index of the list, I imagine a shallow copy is fine.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: