I've been trying to figure out for some time why sometimes I get a copy of my data and sometimes a reference. Then I found out about reference types
and value types
. So my life changed and I started using this info when coding.
Now I am making a custom editor in Unity. I have an Ability
class, which contains a Buff
list (list of Buff classes). So each ability that i have can contain multiple buffs.
When editing the ability variables in the database, I first get a copy of the ability that I am using to not edit them directly but to edit the copy and then save the copy into the database when done. However I still seem to make copies with one line and not with the other. So now it seems I am not referencing a reference type but making it behave like a value type. I don't understand why this is.
//This constructor is used to make a copy of an existing Ability in the database
public Ability(Ability cloneFrom)
{
buffs = new List<Buff>();
//This will work, not cause a reference but actually takes a copy.
//I don't understand that because I am using Add()on a class (reference type)
for (int x = 0; x < cloneFrom.buffs.Count; x++)
buffs.Add(cloneFrom.buffs[x]);
//This will create a reference as expected
buffData = cloneFrom.buffData;
}
The only thing I could imagine is that List.Add() actually makes the copy, but I haven't been able to confirm.
Really quick, make sure you understand the difference between a class
and an object
. A class is the cookie cutter; an object is the cookie.
I think Ron Beyer (from the comments) hit the nail on the head -- you're probably saying you want to keep the lists in sync so that the buffs
of one Ability
object stay in sync with another Ability
object.
This will only work if you assign one object's buffs to another's.
If you call Add
, then you'll get a reference to the buff, but new buffs will not be added.
You mentioned value vs reference types; the quick list is as follows (someone jump in here and correct me)
Value types
Reference types
There is one case you should be aware of:
public class Ability {
public int Score { get; set; }
public Ability(int score) {
Score = score;
}
}
public static void KillReference(Ability ability) {
// When we execute the next line, the ability
// from the original scope will stay the same
ability = new Ability(2);
}
public static void Main() {
Ability ability = new Ability(5);
KillReference(ability);
// ability.Score is still 5
}
OHGODWHY
When you pass a reference type to a function, you're effectively passing a "copy" of a reference (this is the same with pointers in C/C++)...you're effective passing a reference by value (confusing, right?).
When you assign that reference to another object, the original object that was referenced is no longer referenced by this variable -- there's a new variable and all changes to ability
will be directed at this new variable (which will be cleared from the heap once you exit the function's scope).
Hope that helps!