Sign in to follow this  

How do I 'delete' and object in C#

This topic is 3294 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am new to C# coming from c++ and the whole thing is driving me mad, lol I have an object that is created using ... myObject = new myObjectClass(); However I want to destroy the object at a certain point but I dont know how to delete it. In c++ this woudl be ... delete myObject; Is there a way to do this in C#? Thank you

Share this post


Link to post
Share on other sites
Quote:
Original post by SelethD
I am new to C# coming from c++ and the whole thing is driving me mad, lol

I have an object that is created using ... myObject = new myObjectClass();
However I want to destroy the object at a certain point
but I dont know how to delete it.


using statement.

Share this post


Link to post
Share on other sites
Ok that really doesnt make any sense to me for some reason, i think the examples are just a bit confusing.

I dont like the 'using' way, just seems so 'hack'-ish

And the other way... I only gather that by assigning the 'null' to an object allows it to be destroyed? Is that correct?


so I would just use.... myObject=null;

???

Share this post


Link to post
Share on other sites
IIRC there are ways to manually tinker with the garbage collector to make it run when you want, but it's generally not recommended - the results can be unpredictable in terms of performance. The 'using' thing is just an automatic way of calling dispose on a disposable object. If a disposable object has been disposed of then it has been marked for garbage collection, but that doesn't necessarily immediately take place.

It's not a hack though because you might have some resource like an exclusive-access file that an object uses that you want to release when it's no longer needed. Calling dispose on the owning object, or having a 'using' block manage it, can release the file early even though the object hasn't strictly been destroyed yet. You can effectively scope resource ownership despite not controlling garbage collection.

Share this post


Link to post
Share on other sites
Yes, setting the last reference to an object to null will mark it for deletion, BUT it will not get deleted right that instance. It's up to the GC to decide when the object is actually deleted.

As a result you can't rely on the destructor for things like closing files and streams, but must make close methods and call them yourself.

Share this post


Link to post
Share on other sites
Oh, and assigning null to a reference to something doesn't necessarily mark it for destruction because some other object may have a reference to it too. Only an object that isn't referenced by anything else will be destroyed. Similar to reference-counted smart pointers in C++ if that helps - the deletion occurs when no references exist.

Share this post


Link to post
Share on other sites
Ok, thanks for all the input. I think until I learn more about it, and feel more comfortable with that aspect of C#, I will just change my coding style to avoid the whole situation.

I appreciate everyone taking time to respond, thank you.

Share this post


Link to post
Share on other sites
Quote:
Original post by SelethD
I will just change my coding style to avoid the whole situation.
You've got it in one, the trick is to write code that doesn't rely on deterministic destruction. It's quite easy to do, the only downside is you must always manually release any resources you acquire (remembering to close files is the common example) because, unlike C++, you can't predict when the destructor will be executed to close it for you.

It's possible to tamper with the garbage collector yourself to force it's hand, but that's more for optimisation purposes than anything.

Share this post


Link to post
Share on other sites
Quote:
Original post by dmatter
It's possible to tamper with the garbage collector yourself to force it's hand, but that's more for optimisation purposes than anything.
Optmization is a tricky thing when it comes to the garbage collector. Very tricky. There are a few things you need to take into consideration to assure correctness when dealing with managed/unmanaged code interop with respect to garbage collection, but that most certainly is not a performance thing. Optimization though?.... very thin ice you be skating on.

The garbage collector is very good though, and not something you should tamper with unless you know really well what you are doing. It is also not going to be getting you free cycles by calling anything similar to C++'s 'delete' on objects in C# that do not explicitly require you to do so [mostly for the purpose of freeing resources that exist in an un-managed library. See the IDisposable interface, which marks things that fall into that catagory]. You most certainly will not be gaining anything by calling 'collect'.

It really is best not to tamper with something that has already been so carefully tuned. Anyway, the only time you need to call it at all is when it isn't obvious exactly when an object leaves scope [the compiler will flag these bits of data for deletion on its own, because it can figure out when you won't use them anymore]. Sure, the compiler can't figure it ALL out [and provably so], but it can tag the overwhelming majority of the data for deletion when it falls out of scope, and do so immediately [rather than waiting for an exhaustive collection cycle]. You, on the other hand, do not have access to these semantics, and for good reason.

Share this post


Link to post
Share on other sites
Quote:
Original post by SelethD
I think until I learn more about it, and feel more comfortable with that aspect of C#, I will just change my coding style to avoid the whole situation.


Which is ideally what you should aim for.

If it helps, the best way I've seen for programmers coming from C++ to think about it is that all reference variables behave like boost::shared_ptr's

Share this post


Link to post
Share on other sites
Quote:
Original post by SelethD
Ok, thanks for all the input. I think until I learn more about it, and feel more comfortable with that aspect of C#, I will just change my coding style to avoid the whole situation.

I appreciate everyone taking time to respond, thank you.

Yeah I find that programmers going from C++ to C# have a hard time accepting automatic garbage collection.
Anyways, if you have to override it you are probably doing something wrong and are most likely going to introduce some hard to find bugs or confusion at the least!

Share this post


Link to post
Share on other sites
Quote:
Original post by dmatter
Quote:
Original post by SelethD
I will just change my coding style to avoid the whole situation.
You've got it in one, the trick is to write code that doesn't rely on deterministic destruction. It's quite easy to do, the only downside is you must always manually release any resources you acquire (remembering to close files is the common example) because, unlike C++, you can't predict when the destructor will be executed to close it for you.

It's possible to tamper with the garbage collector yourself to force it's hand, but that's more for optimisation purposes than anything.


That's something I love about C++: you can make a class that acquires something in the ctor, and releases it in the dtor, and this can be anything, including a file, a mutex, a resource being taken or not, a counter, etc...

The brillant thing is that automatically at the end of a scope the destructor is called and so the action is performed.

Is such a system not possible in garbage collected languages then?

Share this post


Link to post
Share on other sites
Quote:
Original post by Lode
That's something I love about C++: you can make a class that acquires something in the ctor, and releases it in the dtor, and this can be anything, including a file, a mutex, a resource being taken or not, a counter, etc...

The brillant thing is that automatically at the end of a scope the destructor is called and so the action is performed.

Is such a system not possible in garbage collected languages then?


I guess it would be possible to do this. C# kind-of does this with its using construct, Ruby uses lambda-expressions to achieve the same, ... But I know of no other language than C++ that uses an "out-of-scope trigger". It probably has to do with closures, where local variables can still be kept alive after a function has returned, so that you're back to nondeterminism when it comes to cleanup. Personally, I'd take closures over destructors any day.

Share this post


Link to post
Share on other sites
Quote:
Original post by SelethD

...

The brillant thing is that automatically at the end of a scope the destructor is called and so the action is performed.

Is such a system not possible in garbage collected languages then?


To a large extent that's what the IDisposable interface and 'using' blocks are for. Except that the memory isn't managed alongside the resource.

For instance, imagine I say "I'm using a disposable object 'A' in the following scope" and object 'A' opens a file, does some work... Then when the scope of the using block closes, Dispose is automatically called on A. That is deterministic and I can rely on the call to close the file. However it doesn't also delete object A's memory allocation. The memory management is up to the garbage collector.

Share this post


Link to post
Share on other sites
Quote:
Original post by PKLoki
Quote:
Original post by SelethD
...
The brillant thing is that automatically at the end of a scope the destructor is called and so the action is performed.

Is such a system not possible in garbage collected languages then?
To a large extent that's what the IDisposable interface and 'using' blocks are for. Except that the memory isn't managed alongside the resource.
To be clear though, IDisposable and using statements are C# specific and not a requisite feature of all garbage collected languages, a la Java.

Share this post


Link to post
Share on other sites
Just to expand, C#'s using statements, when used on an object, are for making sure the object is properly and automatically disposed of. It is like the lock statement - you can just use Monitor.Enter/Monitor.Exit, but then you have to make sure it gets called on every return/break/etc and not skipped. It is actually a much cleaner alternative to using .Dispose() manually, where applicable. I use it all over the place for disposable objects that only live in a single method.

Share this post


Link to post
Share on other sites
Quote:
Original post by Lode
Is such a system not possible in garbage collected languages then?


Yes you can do something like this in .NET. However, in general practice, you do not want to do this.

The object class in .NET contains a protected virtual function named Finalize. The Finalize method serves as a destructor for the .NET languages. In fact, in C# you do not override the Finalize method. Instead, you use the C++ destructor syntax. In reality, this is just syntactic sugar for overriding the Finalize method.

The garbage collector will call this method once it is determined that the object is ready for finalization (release). The finalize method is provided to ensure that any unmanaged memory/handles are cleaned up prior to the managed memory being released. Otherwise, a memory leak could occur.

Because you cannot guarentee when the garbage collector will make a collection, you never want to fully rely on the destructor for cleanup. In practice, it is best to inherit the IDisposable interface when dealing with unmanaged code. The Dipose method provides a means to explicitly tell the unmanaged memory to be released. Often it is common to also automatically call the Dispose method from the Finalize method(if it was not previously called). This ensures that that the unmanaged memory will be released at some point in the event that the Dispose method was not properly called in the first place.

See "Digging into IDisposable" by Shawn Farkas for a well written article on using IDisposable and the Finalize method together. Make sure to click the '+' next to each of the 'Figure' labels to see all of the code. If you have a MSDN Magazine subscription, the article was also in the July 2007 issue (page 17).

Share this post


Link to post
Share on other sites
Quote:
Original post by Billr17
Because you cannot guarentee when the garbage collector will make a collection, you never want to fully rely on the destructor for cleanup.


And as an interesting note, .NET at least guarantees that the destructor will be called.

Java does not.

Share this post


Link to post
Share on other sites
Quote:
Original post by SamLowry
Quote:
Original post by Lode
That's something I love about C++: you can make a class that acquires something in the ctor, and releases it in the dtor, and this can be anything, including a file, a mutex, a resource being taken or not, a counter, etc...

The brillant thing is that automatically at the end of a scope the destructor is called and so the action is performed.

Is such a system not possible in garbage collected languages then?


I guess it would be possible to do this. C# kind-of does this with its using construct, Ruby uses lambda-expressions to achieve the same, ... But I know of no other language than C++ that uses an "out-of-scope trigger". It probably has to do with closures, where local variables can still be kept alive after a function has returned, so that you're back to nondeterminism when it comes to cleanup. Personally, I'd take closures over destructors any day.


Python's with statement also does something similar.

While you should the garbage collector do it's job in C#, you should be a good citizen and release other resources when you're done with them. Employing using statements with files (and other os resources) is a Good Thing(tm).

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
Quote:
Original post by Billr17
Because you cannot guarentee when the garbage collector will make a collection, you never want to fully rely on the destructor for cleanup.


And as an interesting note, .NET at least guarantees that the destructor will be called.

Java does not.


.NET:
"due to the non-deterministic nature of finalization the framework does not and cannot guarantee that the Finalize method will ever be called on an instance. Hence, you cannot rely upon this method to free up any un-managed resources (such as a file handle or a database connection instance) that would otherwise not be garbage collected by the GC."
-http://www.devx.com/dotnet/Article/33167/0/page/2

However in Java there's a sure-fire way to track object garbage collections using ReferenceQueues:
http://www.ibm.com/developerworks/java/library/j-refs/

Share this post


Link to post
Share on other sites
C# spec, page 86. Any objects not yet garbage collected are finalized prior to application termination unless you explicitly suppress it.

So it could be argued that such a requirement doesn't cover hard crashes of the app or framework. Though I doubt that C++ destructors offer a better guarantee.

[Edited by - Telastyn on December 7, 2008 10:10:44 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
C# spec, page 86. Any objects not yet garbage collected are finalized prior to application termination unless you explicitly suppress it.


To add to your statement :-)

The original link I provided about the Finalizer states:

Quote:

This method is automatically called after an object becomes inaccessible, unless the object has been exempted from finalization by a call to SuppressFinalize. During shutdown of an application domain, Finalize is automatically called on objects that are not exempt from finalization, even those that are still accessible. Finalize is automatically called only once on a given instance, unless the object is re-registered using a mechanism such as ReRegisterForFinalize and GC.SuppressFinalize has not been subsequently called.


Generally you would not call GC.SuppressFinalize on an object without good reason. In most cases it is only used in the Dispose methods. If Dispose is invoked manually, there should be no reason for the Finalizer to also attempt to release the same unmanaged resources. However, if something occurs where Dispose is never called, the Finalizer should be allowed to run. This scenario could occur if you are unable to make use of the C# using statement. For instance, you could have an object that must create a network connection and must remain opened. In this case, creating an object and disposing it within the same scope would be unsuitable.

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
C# spec, page 86. Any objects not yet garbage collected are finalized prior to application termination unless you explicitly suppress it.

So it could be argued that such a requirement doesn't cover hard crashes of the app or framework. Though I doubt that C++ destructors offer a better guarantee.


Of course, you'd be hard pressed to find a hard crash in a C# program [grin]

Also, I believe the CLI does not require that finalizers be run, but the C# spec does, which is what is causing this confusion. I think the C# spec takes precedence over the CLI spec, since it's on a higher level.

This from the CLI spec:
Quote:
[Note: Since programmers might depend on finalizers to be called, the CLI should make every effort, before it
shuts down, to ensure that finalizers are called for all objects that have not been exempted from finalization by
a call to SuppressFinalize. The implementation should specify any conditions under which this behavior
cannot be guaranteed. end note]

Share this post


Link to post
Share on other sites

This topic is 3294 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this