tags:

views:

368

answers:

6

I have an object that is generated in one class

public class CreatingClass
{
    public T CreateObject<T>(Dictionary<string, object> parameters) where T : IMyInterface, new()
    {
        ....
    }

    public void DestroyObject(IMyInterface objectToDestroy)
    {
        ....
    }
}

I call this function from a client class, then at times need to nullify it through my application by the creating class.

Can I do something like the following

public class ClientClass
{
    MyObject obj;
    CreatingClass creatingClass = new CreatingClass();

    private void AFunctionToCreateMyClass()
    {
        obj = creatingClass.CreateObject<MyClass>(parameters);
    }

    private void AFunctionToDeleteMyObject()
    {
        CreatingClass.DestroyObject(obj);
        Assert.IsNull(obj);//Doesn't fail
    }
}

I had tried objectToDestroy = null, but didn't think it would work (and it didn't)

+4  A: 

What you want is

public void DestroyClass(ref IMyInterface objectToDestroy)
{
    ....
    objectToDestroy = null;
}

This is will set your local reference to null

Binary Worrier
Makes complete sense
johnc
But will only set one reference to the object to null. The object itself is not destroyed, and other references to it are still valid.
GvS
GvS: That's pretty much true for every object in a garbage collected environment. That's why (amongst other reasons) it is a good idea to minimize the number of references to an object.
DrJokepu
+2  A: 

[Your 'CreatingClass' is usually termed a factory]

Not sure why you'd be concerned with nullifying an object; it will be garbage collected only after all 'root' references to it have been removed. But if you change to:

 public void DestroyClass(ref IMyInterface objectToDestroy)   
 {       
     ....    
     objectToDestroy = null;
 }

and call as:

private void AFunctionToDeleteMyObject()    
{        
   CreatingClass.DestroyObject(ref obj);    
   Assert.IsNull(obj);  
}
Mitch Wheat
+3  A: 

All parameters in C# are passed by value, so if you want to modify the reference itself, you need to pass it using the ref keyword.

Brian Rasmussen
+3  A: 

Are you looking for the IDisposable pattern?

GvS
+7  A: 

Note that you can't actually destroy an object; you are subject to the rules of garbage collection. At a push, you could check for IDisposable and call Dispose(),

You can use the ref samples provided, but I'm not sure there is much point; it is simpler just to clear the field with "obj = null;".

The ref usage could get confusing, since that works on the variable - i.e. if you do:

var tmp = obj;
DestroyObject(ref tmp);

then obj will still be the original value. Unless you have a good reason, I don't recommend the ref approach.

Marc Gravell
+1. Nice reference count example.
Mitch Wheat
That isn't a "reference count example"; it simple illustrates how "ref" works on the variable not the object... GC doesn't use reference counting
Marc Gravell
+1: Far more complete answer than mine.
Binary Worrier
Also, it's almost always better not to set "obj = null". Just leave the GC to decide when an object is no longer used.
Joe
@Marc: "reference count " was the wrong words to use. I meant it nicely shows how having a ref stops it being GC'd
Mitch Wheat
A: 

A little clarification on the answers supplied...

Parameters in C# are passed by their type, value for value types, reference for reference types. You however, are passing an interface which could relate to a class (reference type) or struct (value type), therefore you need to explicitly declare it as a ref variable.

However, what you should really follow (as mentioned previously) is the IDisposable pattern, which was designed for this functionality.

EDIT: Parameters are passed by value, but for reference types the reference is the value. Therefore is you destroy the refence in the function, the original reference type is unaffected. If you make a change to the reference variable, i.e. modifying data in a dataset, the original reference type is updated outside of the function.

ck
No, parameters are *always* passed by value by default. For reference types, the parameter value *is* the reference - but that's passed by value. See http://pobox.com/~skeet/csharp/parameters.html
Jon Skeet
"If you make a change to the reference variable, i.e. modifying data in a dataset" - modifying a dataset is modifying the instance, not the variable. There is an important difference.
Marc Gravell