List newList new List Unexpected Behavior
private void SomeVoid(){
......
List<myClass> newList = new List<myClass> ;
newList = someList;
......
......logic
List<myClass> newList2 = new List<myClass> ;
newList2 = newList;
......
...... logic
List<myClass> newList3 = new List<myClass> ;
newList3 = newList2;
...... more logic
someList[cnt]._points = newList3[cnt]._points;
......
}
**At this point in the program someList[cnt] is not only receiving that one particular variable but all other variables associated with newList3[cnt] .
public class myClass{
public int _memberNo;
public int _points;
public int _rank;
public string _name;
public int[] _games;
}
Good Evening All: Above I have an example of my code {as an example} that is currently, completely befuddling me.
Expected Behavior: Well, how I understand it to be. The first line is meant to "create" and "reference" a new List<> of type myClass, newList. The second line of code is meant to set the values of newList = to the values of someList which is of the same type myClass. This works, this behavior is fine. Changing or assigning value to only one variable in someList[] should not affect the other variables in someList[].
Observed Behavior: Tum tum tum!! Assigning a single variable in someList[] from newList3[] assigns all other variables found in newlist3[]
Questions: Yes, 5 of them. Please Note that Q1 to Q3 has been answered by @incorrect 's comment. I would please still like an answer to accept.
Am I expecting the wrong Behavior from my declarations/script?
Is the Observed Behavior = Intended Behavior?
Additionally Is the Observed Behavior - A Reference as Apposed to a new Declaration thing?
If so, How would I achieve the Expected Behavior? That is create a newList that only holds the same values as someList, that can be used to only change, affect the intended variable as above.
If you would be so kind, please reference some material that i could understand this better? If an explanation would be considered a far to daunting task :) . {I honestly don't mind reading up on this myself. I'm just not finding any documentation at this time.}
Additional Information: --Unity Science!!-- {Why so many newList*{I have been informed of this, see comments}*? Round Robin Calculator :/ Rankings :/ Points :/ Tie breaker :/ Unity Noob :/ etc.}
C# {or OOP programming in general} is not my 'first language', so please mind the lingo |:0. Classically Trained in Pascal.
Unity Personal 5.0.2f1, Mono 4.0.1, Win 7 Ultimate Service Pack none ^.
Yes I have looked for similar questions, Google, Unity Answers, stack exchange and Bing {at this point I was willing to try anything}. I must be looking for the wrong thing.
Barring all of this, my program works perfectly fine, no bugs, no nothing. I just want to make sure I'm understanding this before moving on to new projects. If I'm honest the behavior is a little of a bonus. But it is for the most part not the Behavior I was looking for.
this As I understand it: temporary declaration List<> of Type Class Declaration in void/function.
Edit: Typo and Some Declarations, moved to help at some point as I was unaware that Default was not the place for this Q.
List is a class. So when you are doing list1 = list2
, you are passing a reference to the list stored in list2 to list1. A reference to the list, not the values. That means that list1 and list2 are now the same list and changing anything in list1 will change list2 as well.
@incorrect Thanks for your swift comment, I apologize for my tardy reply :D. So I am referencing as appose to equating!
So that is Yes on 1, yes on 2 and yes on 3.
$$anonymous$$ay I assume that:
private void SomeVoid(){
......
......logic
List<myClass> newList2 = new List<myClass> ;
for(int cnt = 0;cnt < newlist.Lentgh;cnt++ ){
newList2.Add(new myCLass() {_memberNo = newlist[cnt]._memberNo ....})
}
......
...... more logic
}
would be the only method of achieving my Expected behavior, or are there other methods I'm just not finding?
Again, thanks for your comment. It has lead me to understand that my script can be cleaned up a lot by not using so many newLists
EDIT: Typo, Additional Information.
Answer by EvilTak · Jan 28, 2016 at 12:52 PM
Since Q1 through Q3 have been answered by @incorrect, I'll answer the fourth (hopefully my explanation does enough to answer the fifth too).
If so, How would I achieve the Expected Behavior? That is create a newList that only holds the same values as someList, that can be used to only change, affect the intended variable as above.
To copy or clone a List into another List (or shallow copy), you can use the new List<T>(IEnumerable<T> collection)
constructor. It copies the elements of collection
into the List being instantiated. Thus to copy the elements of someList
into newList
, you will use
newList = new List<myClass>(someList);
If you go ahead and use this code in your method, you'll still notice the same problems. Even though the Lists are two different instances, changes made in newList
are still reflected in someList
. Why?
This is because objects of a class in C# are stored and called by reference, which is why although newList
and someList
have different copies of the reference to each object initially added to someList
, both the references still point to the same object in memory. Which is why you can say that both the Lists indirectly contain the same objects.
To get around this problem, you could either implement a Clone()
method or a copy constructor in myClass
. For this case, I'd use the latter, which would be implemented as follows:
public myClass(myClass other)
{
_memberNo = other._memberNo;
_points = other._points;
// And so on
}
Since you need to do what is called a deep copy, you can't use the new List<T>(IEnumerable<T> collection)
constructor, since it performs just a shallow copy of the collection
. Instead, you will have to instantiate each object yourself. The code to do that:
// We're instantiating the list to the desired capacity beforehand so that
// newList doesn't have to be resized
newList = new List<myClass>(someList.Count);
foreach(myClass item in someList)
newList.Add(new myClass(item));
You can also refer to this question on Stackoverflow, which shows you many more methods (mostly including Linq, which I didn't use because I don't know whether you know about it).
EDIT: Code conventions tip: class and method names in C# use PascalCase, so the name of the class should be MyClass
instead of myClass
.
@Evil Tak , Thanks for great explanation and example. I will be accepting your answer :D. Now I can move on to the next project!
"Additionally, even after nit picking my bad spelling and grammar, i forwent' Code Conventions :/... $$anonymous$$y $$anonymous$$d was probably just raw. ~I believe now that that was a conspiracy brought on by the incessant meanderings of the newlist dilemma of 2016~
But do not fear :D, I have not transgressed such atrocities in me code." Bruce James Boyd 01/09/2016 10:31A$$anonymous$$
hmm didn't think my 'quote' would out shine the comment. This is what you get when you wanna express joy with sarcasm :/....
EDIT: Grammar, Who still uses :D?, $$anonymous$$ade the comment a heading