开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜