0

I have the following method in an Universe class:

public IWorld CreateWorld(string name) {

    //Validations and stuff...

    IWorld world = new World(name);
    worlds.Add(name, world);
    return world;
}

A new World instance is created, and added to a Dictionary<string, IWorld>. Then, I proceed to return the same reference that was added to the dictionary.

All good so far.

In the same Universe class, I also have the following method:

public void DestroyWorld(string name) {

   //Validations and stuff...

   IWorld world = worlds[name];
   worlds.Remove(name);
   world.Dispose();
   world = null; // <- Setting the object to null
}

Here I am taking the object reference from the dictionary, disposing it and then setting it to null.

Outside this project, I have my Main class:

public static void Main(strig[] args) {
   IWorld world = Universe.Instance.CreateWorld("Solarius");
   Console.WriteLine(world.Age); //Prints out the world's age
   Universe.Instance.DestroyWorld(world.Name);
   Console.WriteLine(world.Age); //NullPointerException not being thrown! Prints out the same world's age
}

Why is this happening? Why am I able to call world.Age, if I set the reference to null in Universe.DestroyWorld method?

Isn't the reference stored on the dictionary the same one I am manipulating in the Main class?

7
  • I don't see the code defining Age. Can you please provide it? Commented Nov 14, 2014 at 17:30
  • It's just a property on the IWorld interface: int Age { get; } Commented Nov 14, 2014 at 17:31
  • Why does the code for DestroyWorld take a string param instead of an IWorld? Commented Nov 14, 2014 at 17:32
  • I have an overload of that method that takes an IWorld, but I really need a string, since its the key for the dictionary Commented Nov 14, 2014 at 17:33
  • I suggest to read albahari.com/valuevsreftypes.aspx or yoda.arachsys.com/csharp/references.html Commented Nov 14, 2014 at 17:35

5 Answers 5

1

You have to remember that when you pass object as an argument to a method what you do you actually pass a copy of a reference. So after passing the object to a method you actually have a two places from which you refer to the object. One is your original one and the other is a copy of the original. At the moment you set to null only the copy.

To get the result you want you can pass the object, and not the name, to the method. And you have to do it using the ref keyword. This way the reference is not copied but the method is using your original reference. So when you manipulate the object in the method you will actually manipulate it through your original reference.

ublic void DestroyWorld(ref IWorld world) {
    world.Dispose();
    world = null; // <- Setting the object to null
}

And use it like that:

public static void Main(strig[] args) {
    IWorld world = Universe.Instance.CreateWorld("Solarius");
    Console.WriteLine(world.Age); //Prints out the world's age
    Universe.Instance.DestroyWorld(ref world);
    Console.WriteLine(world.Age); // NullReferenceException
}

I know it's fairly different from your original code but it will work the way you would expect. And I strongly recommend this article on parameter passing in c#, particularly the part about passing reference types by 'ref' keyword:

http://yoda.arachsys.com/csharp/parameters.html

And here you can find the same mechanism explained in a more visual fashion:

http://rapidapplicationdevelopment.blogspot.co.uk/2007/01/parameter-passing-in-c.html

Sign up to request clarification or add additional context in comments.

Comments

0

Setting world to null doesn't set the object to null. It sets the object reference to null.

The idea of setting an "object" to null doesn't even make sense.

Comments

0

You set the local variable of the DestroyWorld method to null. That doesn't set every variable everywhere else in the entire application that is referencing that World instance to null, just that one variable. In fact, it's impossible for the DestroyWorld method to do anything that would set the variable in Main to be null.

3 Comments

So, the local variable in my method is different from the one in Main? Does that mean I have two different copies?
@MatiCicero You have two copies of the reference to the object, yes. Both copies are referencing the same object. When you destroy a piece of paper that has your home address written on it does it destroy every other piece of paper in the whole world that has your home address written on it? Does it destroy your house?
Thank you for the real life example. I think I now understand it correctly.
0

You have to understand that you are working with references to an object, not the object itself.

//this sets the someVar to a reference to a new object
var someVar = new World(); 

//this sets the *variable* to a NULL reference
//but it doesn't do anything to the original object
someVar = null;

The way objects die is through garbage collector which, in simple terms, counts how many live references are there to an object (the address at which it is located in memory) when that count is 0 the garbage collector is allowed to allocate new objects in that same memory space.

Comments

0
public IWorld CreateWorld(string name) {
IWorld world = new World(name);
worlds.Add(name, world);
return world;

}

Where you are creating the world , you return an instance of IWorld to the code

But when you are deleting the world you are not returning it

public void DestroyWorld(string name) {
IWorld world = worlds[name]
worlds.Remove[name];
world.Dispose();
world = null;

}

And the world that you are setting as null is the one INSIDE THE SCOPE of the funcion , so or you return the Iworld that you want to put as null , or you pass the IWorld object in the function and set that one as null;

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.