c# - reference type referencing another reference type
Note: This applies to both List and ArrayList
Take a look at the following simple code:
class Creature
开发者_StackOverflow中文版{
public string Name;
}
class Game
{
// This is a reference type
public Creature CurrentCreature;
}
class Program
{
static void Main(string[] args)
{
// First, we'll create 2 objects and let the
// reference type "CurrentCreature" points to one of them
Creature dragon = new Creature();
dragon.Name = "Dragon";
Creature Unicorn = new Creature();
dragon.Name = "Unicorn";
Game game = new Game();
game.CurrentCreature = dragon;
// Now we'll create a list which will contain
// the reference type "CurrentCreature"
List<Creature> list = new List<Creature>();
list.Add(game.CurrentCreature);
foreach (Creature c in list)
{
Console.WriteLine(c.Name); // Output is "Dragon"
}
// Now, we'll let "CurrentCreature" point to a different object
game.CurrentCreature = unicorn;
// The reference in the list still pointing to the original object!!!
foreach (Creature c in list)
{
Console.WriteLine(c.Name); // Output is "Dragon"!!!
}
Console.ReadLine();
}
}
I checked how a list adds an item and there is no instantiation of a new object. This is List.Add method (using Reflector tool)
public void Add(T item)
{
if (this._size == this._items.Length)
{
this.EnsureCapacity(this._size + 1);
}
this._items[this._size++] = item; // No instantiation
this._version++;
}
So, why is this happenning? The element in the list should be a reference to the object pointed to by "CurrentCreature" or is it not? Isn't it similar to the following code if we remove the list?:
class A
{
public B X;
}
class B
{
public string Name;
}
....
A a = new A();
B b1 = new B(); b1.Name = "b1";
B b2 = new B(); b2.Name = "b2";
a.X = b1;
Console.WriteLine(a.X.Name); // output: b1
b1 = b2;
Console.WriteLine(a.X.Name); // output: b1
When you do
game.CurrentCreature = unicorn;
You overwrite the pointer in game.CurrentCreature with one to the unicorn object. The array still has a pointer to the dragon object. It shouldn't be changed, this is how pointers work.
Edit:
A little explanation of what happens with the pointers:
First you created 2 objects
Creature dragon = new Creature();
dragon.Name = "Dragon";
Creature Unicorn = new Creature();
dragon.Name = "Unicorn";
This made dragon have a pointer to your dragon object, and unicorn have a pointer to your unicorn object.
Then you set the pointer of game.CurrentCreature to dragon's pointer.
game.CurrentCreature = dragon;
Then you add a pointer to dragon, the current creature, to the list
List<Creature> list = new List<Creature>();
list.Add(game.CurrentCreature);
Then you replace the pointer in game.CurrentCreature(was dragon) with a pointer to the unicorn object.
game.CurrentCreature = unicorn;
This will in no way affect the pointer held in the dragon object.
Cheers,
Reference types don't just change.
You're adding the creature to the list, not the game. Then you change the game's reference to use anoter creature; but the creature referenced in the list remains the same, thus it outputs the same result again.
Reference is copied to a list, not an object. After list.Add(myobject);
you get two references (that are referring to the same object): myobject and those one that is in a list.
精彩评论