Sunday, March 20, 2011

C# Can I nullify an object from another class

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)

From stackoverflow
  • What you want is

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

    This is will set your local reference to null

    johnc : Makes complete sense
    GvS : 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.
    DrJokepu : 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.
  • [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);  
    }
    
  • 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.

  • Are you looking for the IDisposable pattern?

  • 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.

    Mitch Wheat : +1. Nice reference count example.
    Marc Gravell : 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
    Binary Worrier : +1: Far more complete answer than mine.
    Joe : Also, it's almost always better not to set "obj = null". Just leave the GC to decide when an object is no longer used.
    Mitch Wheat : @Marc: "reference count " was the wrong words to use. I meant it nicely shows how having a ref stops it being GC'd
  • 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.

    Jon Skeet : 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
    Marc Gravell : "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.

0 comments:

Post a Comment