Saleh Al-Abbas
Saleh Al-Abbas

Reputation: 155

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
{
    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

Upvotes: 0

Views: 344

Answers (3)

Stefan H
Stefan H

Reputation: 6683

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,

Upvotes: 2

levanovd
levanovd

Reputation: 4165

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.

Upvotes: 0

Lucero
Lucero

Reputation: 60190

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.

Upvotes: 1

Related Questions