0

What is the correct code syntax (Set the StringBuilder instance to Nothing at the end the function) when use stringbuilder in a function that return a string? Usually i try to use the statement 'using', but StringBuilder don't implement iDisposable.

To be more precise: i want to release the memory occupied from the StringBuilder instance when GC will run, so i'd like to set the StringBuilder instance to Nothing at the end of the Function.

Please do someone know 'where' should i set the StringBuilder instance to Nothing?

Here's the code.

Function GetString() As String
    Try()
        Dim sb As New StringBuilder
        sb.AppendLine("my first line")
        Return sb.ToString()
        'Should i put here 'sb = Nothing' ?
    Catch()
        Return Nothing
    End Try()
End Function

Or it's better this solution?

Function GetString() As String
    Dim sb As New StringBuilder
    Try()
        sb.AppendLine("my first line")
        Return sb.ToString()
    Catch()
        Return Nothing
    End Try()
    'Or should i put here 'sb = Nothing' ?
End Function
Marcello
  • 438
  • 5
  • 21
  • You don't need to set the StringBuilder to nothing, .net garbage collector will handle all that is necessary. Why do you think you need to do that? As you seem to already know, when a class is implementing IDisposable, you need to worry about this and use the using-block. – Esko Jun 12 '19 at 08:55
  • @Esko But StringBuilder doesn't implement idisposable. so i can't write 'Using sb as new StringBuilder'. And why you say i don't need to set the StringBuilder To Nothing? Shouldn't be a good practice destroy all variables not more used, without waiting the GC? – Marcello Jun 12 '19 at 09:09
  • 1
    There's no such thing as "destroying a variable". If a type implements the `IDisposable` interface then you should dispose objects of that type when you are done with them. If you only use them in a defined scope, a `Using` block is the best way to do that. If a type doesn't implement `IDisposable` then there's nothing to "destroy". You can set a variable to `Nothing` to make the object it referred to available for garbage collection sooner but, if the variable falls out of scope immediately anyway, that would be pointless. Only clear a variable that will be in scope for some time after. – jmcilhinney Jun 12 '19 at 09:12
  • @jmcilhinney sorry, with destroying i was meaning set it to Nothing. So in the example, where would you set the StringBuilder to Nothing? and why? – Marcello Jun 12 '19 at 09:23
  • Like stated, there is no need to set the StringBuilder to Nothing. The reasons have also been explained. Further, any line of code written after the `Return` statement will **not** be executed. So neither of your examples would actually server any purpose. You will not actually have the opportunity to set the StringBuilder to nothing. See the response the [this question](https://stackoverflow.com/questions/4820952/set-variables-to-nothing-is-a-good-practice) – Anu6is Jun 12 '19 at 09:26
  • @Anu6is Thanks for answer, but sorry, i didn't see noone explained me why shouldn't i set the StringBuilder to Nothing before close the Function. I mean, should be a good practice set all variables used to Nothing, when a procedure it's closed. So why i shouldn't set the StringBuilder to Nothing? I mean, if i have 100 functions, and i don't set all variables used on those Functions to Nothing, would mean that when the GC runs, don't release the occupied memory from not used variables. ...Did i mistake something? – Marcello Jun 12 '19 at 09:42
  • jmcilhinney included some reasons in the response they gave above. Additionally, the answer I linked also states that it is unnecessary to set your variables to Nothing and goes further to show a case in which you might want to set it to Nothing. Noting that it's a somewhat rare case. So long as your variables are properly scoped, you generally don't need to worry about things sitting around in memory. GC will clean up these variables without you having to set them to Nothing. The fact that they are no longer referenced is enough. – Anu6is Jun 12 '19 at 09:50
  • @Anu6is referred to the link you provided me, that link conform me that i should be right: StringBuilder it's a ReferenceType, so should be a good practice set it to Nothing asap after used it. Maybe i mistake something. – Marcello Jun 12 '19 at 09:53
  • @Anu6is sorry, but as you wrote jmcilhinney wrote same things i asked: 'You can set a variable to Nothing to make the object it referred to available for garbage collection sooner ' and it's the point of my question: Because i want to release memory quickly, for the GC, what is the best code to set a StringBuilder to Nothing in a function that return the StringBuilder ToString() Value? – Marcello Jun 12 '19 at 09:57
  • 1
    Like I stated before, it's a matter of scoping. Once a variable falls out of scope (Return is called), it’s popped off the stack and the reference is removed. If you can’t wait for the scope to exit, you likely need to refactor your code. The example you gave is relatively simple, but if by chance the method was longer and did a lot more things, you could simply break those into smaller methods, thereby managing the scopes of the variables declared. Further to that, there is no way to set the variable to Nothing **after** you've already called Return. And clearly, you can't set it before. – Anu6is Jun 12 '19 at 10:10
  • @Anu6is Thank you very much for your help, i would like to understand precisely if an isnstance of a ReferenceType NOT set to Nothing in a Function, will not be processed and destroyed by the GC, and for how long the instance of that ReferenceType will occupy the memory. I suppose that if the instance it's not set to Nothing, will occupy a part of memory for entire life of the program. – Marcello Jun 12 '19 at 10:21
  • `if an isnstance of a ReferenceType NOT set to Nothing in a Function, will not be processed and destroyed by the GC` - It will be cleared by the GC `I suppose that if the instance it's not set to Nothing, will occupy a part of memory for entire life of the program` - It will not sit in memory forever. – Anu6is Jun 12 '19 at 10:27
  • @Anu6is Yes, you repeated what i said. except that i obviously never said that the variable will occupy a part of the memory forever. Obviously because when the program end, the OS will 'release' all the memory occupied from the program. So at this point: i asked what is the best practice to set an instance of a ReferenceType to Nothing, inside a Function that Return the Value of that instance. Another member has provided me with an example, equal the one i provided in the question. Maybe someone who know the difference between set to Nothing inside/outside a Try-Catch block could help 'us' – Marcello Jun 12 '19 at 10:57
  • It is NOT best practice to set a variable to Nothing. Yes I repeated your questions and provided my responses. By forever I meant the duration of the program. Additionally, your example and the answer provided is somewhat abusing try/catch. – Anu6is Jun 12 '19 at 11:05
  • @Anu6is Again thanks for your help. But honestly i think you mistake. On internet, on every books, everywhere it's explained that IT'S best practice to set a variable to Nothing after use it. Please, can you help me to understand where you had read that it's NOT best practice to do it? – Marcello Jun 12 '19 at 11:12
  • [link1](https://forums.asp.net/post/1652603.aspx) | [link2](https://stackoverflow.com/questions/3903878/c-should-object-variables-be-assigned-to-null) | [link3](https://devblogs.microsoft.com/csharpfaq/should-i-assign-null-to-my-local-variables/) | [link4](https://www.infoworld.com/article/2986753/best-practices-to-facilitate-garbage-collection-in-net.html) | [link5](https://blog.stephencleary.com/2010/02/q-should-i-set-variables-to-null-to.html) | [link6](http://codebetter.com/karlseguin/2008/04/28/foundations-of-programming-pt-7-back-to-basics-memory/) – Anu6is Jun 12 '19 at 11:39
  • Note that in particular when dealing with **local** variables (as used in your example) no one suggests setting these values to null/nothing. Static variables or fields/member/global variables can be set to null since they have a larger scope and you may want to explicitly remove them from memory by clearing the reference before the GC considers it out of scope. – Anu6is Jun 12 '19 at 11:45
  • @Anu6is Thanks, this is a good answer. Confirms in part this detailed link: https://blog.stephencleary.com/2010/02/q-should-i-set-variables-to-null-to.html .But to be honest, i'm also right, sorry to go on: it's to understand well. The situation vary with programs. I understand, in general, it's not a good practice to write 'unnecessary code' because Framework provide GC that release unused memory. But it's also true that if i have a program that loops days/months, but runs a function one time, and a local variable it's not set to null, it has no sense don't release memory for months. OK? :) – Marcello Jun 12 '19 at 12:32
  • No, that is not true. That function that is run once, will release the variable, so long as it is a **local** variable, when the function ends. This is why I keep mentioning **scope** in my responses. Your variable would be added to memory when declared and removed once the method that declared it exits. Regardless of you the overall program executing in some sort of loop. – Anu6is Jun 12 '19 at 12:45
  • You said: _On internet, on every books, everywhere it's explained that IT'S best practice to set a variable to Nothing after use it_ - Can you provide some links that show this because in the .Net world it is **not best practice** to set variable to `Nothing`. – Chris Dunaway Jun 13 '19 at 14:55
  • @ChrisDunaway Thanks for helping me. Please i wrote an answer, if you want to correct me, you can do it, posting on my answer. Thanks for your help. – Marcello Jun 13 '19 at 19:41

2 Answers2

0

I wrote the same function in c#, in your case is not necessary to clean the "stringbuilder" variable but, to make certain clean after the return statement you can use a try… finally block.

static string GetString()
{
     StringBuilder sb = new StringBuilder();
     try
     {
          sb.AppendLine("myfirstline");
          return sb.ToString();
     }
     finally
     {
          sb = null;
     }
}
bdn02
  • 1,500
  • 9
  • 15
  • Thank you very much for yuor help, bdn02. I think that because i declared the StringBuilder instance 'outside' the Try-Catch block, i could set it to Nothing also Outside the Try-Block Catch. I think a best practice would set it to Nothing as i wrote in my second example (outside of Try-Catch). – Marcello Jun 12 '19 at 10:46
  • 1
    No, best practice would not be to set it to `Nothing`. As you have been told over and over, there is no point setting that variable to `Nothing` because the variable itself ceases to exist immediately after. The only reason to set a variable to `Nothing` is if the variable itself will remain in scope for a long time, thus preventing the garbage collector finalizing the object it refers to. If the variable goes out of scope then the that reference to the object no longer exists so the effect is the same. Setting the variable to `Nothing` is pointless. Doing pointless things is bad practice. – jmcilhinney Jun 12 '19 at 13:29
  • @jmcilhinney thanks, you're right, now i understand. GC process unused methods asap, so memory occupied from local variables are quickly released. Thank you for your precious help. – Marcello Jun 13 '19 at 19:47
0

Ok, thanks to some users (@jmcilhinney, @Anu6is) who spent lot of time helping me to learn, i post my answer.

The correct syntax to release local resources in a method is this:

Function GetString() As String
    Try()
        Dim sb As New StringBuilder
        sb.AppendLine("my first line")
        Return sb.ToString()
    Catch()
        Return Nothing
    Finally()
        'N.B. Good practice don't write
        'sb = Nothing
    End Try()
End Function

Please, note that in the Finally statement i wrote 'Good Practice' to don't write

sb = Nothing

Why? Because every Local variable inside of a method, when the execution of the code exit the method, are automatically 'cleaned' by the Garbage Collector (the GC release the memory previously occupied by the local variables, but if the execution of the code will use again the method before the garbage collector runs, the memory area previously occupied will be riallocated by the pointer of the new instances of the local variables).

Different approach is when a method uses a non-local variable:

Class MyClass
    Dim sb As New StringBuilder

    Friend Function GetString(ByVal text as String()) As String
        Try()
            For Each Txt As String In text
                sb.AppendLine(Txt)
            Next Txt
            Return sb.ToString
        Catch()
            Return Nothing
        Finally()
            'Here i can write:
            'sb.Clear
            'or
            'sb = Nothing 
        End Try()
     End Function
 End Class

Why in this case could be a good practice to set the variable to Nothing or (in this case) release the memory occupied by the StringBuilder Value?

Could be, if in example, i use the method in the beginning of the program, and not more.

Or if the StringBuilder 'store' an huge amount of data, for lot of time.

In this case, we 'choose' to set the StringBuilder to Nothing, to release occupied memory, that will not be used by the program.

This article, explain well the cases when, it's good practice to set a variable to Nothing, inside of a method.

https://blog.stephencleary.com/2010/02/q-should-i-set-variables-to-null-to.html

After this, a question could come in mind:

'But if i wait that the Garbage Collector will 'release' memory, for how long i have to wait? ...Ticks ...Milliseconds, ...Seconds, ...Minutes...?

Here a link that can help:

https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals

Marcello
  • 438
  • 5
  • 21