2

I have a function like the following:

Public Function testFunction(ByVal input_string As String) As String

    Dim s As New StringBuilder()
    Dim c As Char
    For i As Integer = 0 To input_string.Length - 1
        c = input_string.Chars(i)
        s.Append(c)
    Next
    Return s.ToString

End Function

but I want know if it's better to explicitly destroy any object, like this:

    Public Function testFunction(ByVal input_string As String) As String

    Dim s As New StringBuilder()
    Dim c As Char
    For i As Integer = 0 To input_string.Length - 1
        c = input_string.Chars(i)
        s.Append(c)
    Next

    Dim t As String = s.ToString
    s = Nothing

    Return t

End Function

or just let the garbage collector do the job for us?

Both the above functions work, but I want only know the best practice for performance...

thank you

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Max
  • 4,965
  • 17
  • 49
  • 64

6 Answers6

6

Setting s = Nothing is pointless as it falls out of scope at the very next instruction thus becoming eligible for garbage collection at that point anyway.

Setting a variable to null/nothing doesn't mean the garbage collection kicks in at that point.

ChrisF
  • 134,786
  • 31
  • 255
  • 325
  • @Mark - ok, bad terminology. I'll remove it. – ChrisF Dec 04 '10 at 16:27
  • 2
    Actually, it's usage that matters, not scope. The object falls out of use before the statement that sets the reference to Nothing. – Guffa Dec 04 '10 at 16:31
  • @Marc - don't apologise. The whole point of SO is to provide accurate and (hopefully) complete answers so pick away. – ChrisF Dec 04 '10 at 16:32
4

It's always better to let the garbage collector do the job for you. Think about it like this: a programmer much smarter than you (and I) carefully optimized the garbage collection routine to make life much simpler and painless for you. It's unlikely that we can do a better job ourselves, and more likely that we'll just interfere.

Basically, objects that are instantiated as local variables will become eligible for garbage collection as soon as they fall out of scope (i.e., that method finishes execution). Your StringBuilder object is going to be garbage collected whenever the garbage collector runs (which is another thing you don't have to worry about—there is no way to know the next time the GC will run).

Setting an object to Nothing literally does nothing (note that this is different than pre-.NET versions of Visual Basic). It will generally be optimized out by the compiler in Release mode, and even if it isn't, it's not helping you in the least.

However, if an object has a Dispose method, you should be calling it. Or better yet, wrap it in a Using statement. But there's still no reason to set its reference to Nothing.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • No, assigning a value to the reference does *not* count as accessing it, so the garbage collector will not refrain from collecting the object before that. – Guffa Dec 04 '10 at 16:34
  • Thank You all, however I voted this bc it's the only one that mentions the dispose method. – Max Dec 04 '10 at 16:39
  • @Max: `Dispose` and GC are orthogonal. `Dispose` is ideally for managing resources that the GC can't handle. So, `Dispose` isn't really germane to this question. – jason Dec 04 '10 at 16:41
  • 1
    @Cody Gray: It's still not correct. The blog posting that you have read is not correct on this point. The garbage collector doesn't care *at all* about the null assignment (neither in debug or release mode), so it doesn't matter if it's optimised away or not. It's only the usage of the object that matters, and assigning a new value to the reference doesn't count as using the previous value. – Guffa Dec 04 '10 at 16:47
  • @Jason: I meant just more accurate – Max Dec 04 '10 at 16:48
  • @Guffa: Interesting. I've come across lots of evidence to the contrary, though I personally have not done any investigation or profiling. So I'm not disagreeing, but I'm curious if you have any reference confirming this. I suppose I'll leave the answer as is and let the comment exchange speak for itself. – Cody Gray - on strike Dec 04 '10 at 16:50
  • @Max: An answer that contains extraneous details is not more accurate. – jason Dec 04 '10 at 17:03
  • @Jason: Usually I prefer the details and implementation notes. Not only 4 lines. – Max Dec 04 '10 at 17:10
  • @Max: Fine, next time you ask a question I'll make sure to include details about the history of World War II, the Byzantine Empire, and the theory of relativity. You seem to be missing the point that `Dispose` is not germane to your question. – jason Dec 04 '10 at 17:20
  • @Jason: you are too comic; i'm not. It's not the World War/etc. I think it's useful for others make a simple note for the dispose method. – Max Dec 04 '10 at 17:38
  • @Cody Gray: If you have found so much information suggesting the contrary, you should try it for yourself. It's easy using a WeakReference and GC.Collect to show that an object can be collected before the reference is assigned null. – Guffa Dec 04 '10 at 18:32
  • @Guffa: I just tested this (though by implementing a finalizer in my own class instead of using a `WeakReference`) and confirmed to myself what you've been saying. I didn't have a chance to test it when I first posted, but I'm glad that I did. Perhaps this was the case with very early versions of the compiler (although it works as you describe as far back as v2.0), or people have just been passing around misinformation for quite a while on the Internet (gasp!). Either way, I'll update my post. Thanks for pointing this out. – Cody Gray - on strike Dec 05 '10 at 05:00
1

If an object doesn't implement IDisposable then you are correct to do nothing (you couldn't free the object if you wanted to).

If an object implements IDisposble you must call .Dispose() - you are using it wrong if you don't. The object can try to protect you from yourself, and call Dispose itself when it is being finalized (destroyed, freed), but objects are not required to do your work for you.

See also

Community
  • 1
  • 1
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
0

Let the garbage collector do this. Classes that implement the IDisposable interface are designed for you to manage pre-garbage collector - meaning that you invoke object.Dispose(). This is because those classes use limited system resources like file handles and GDI brushes. If it doesn't implement IDisposable then its usually safe to just let the garbage collector handle it.

cfeduke
  • 23,100
  • 10
  • 61
  • 65
0

The objects there are all going to get destroyed when the code ends the function, as the variables are out of scope. The s = Nothing is redundant because on the next run of the GC, those objects will be destroyed anyway.

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
  • They might not get destroyed when the function returns; the GC is non-deterministic. You don't know when it will run and those objects will be destroyed – jason Dec 04 '10 at 16:27
0

The whole point of garbage collection is so that you don't have to manual manage memory anymore. Let the garbage collector do its job.

Additionally, setting a variable to Nothing does not mean that the GC is going to kick in and free the memory; the GC is non-deterministic. It could run immediately, it could run in four score and seven years.

jason
  • 236,483
  • 35
  • 423
  • 525