For example, such a code, it loads images from files and considers the maximum width and total height:

List<Bitmap> bitmapsList = new List<Bitmap>(); foreach (string fn in fileNames) { Bitmap bmp = new Bitmap(fn); // Интересует вот эта строка bitmapsList.Add(bmp); if (bmp.Width > maxWidth) maxWidth = bmp.Width; totalHeight += bmp.Height; } 

Question: is it more correct to create a Bitmap bmp object in a loop, or declare it before a loop? What happens to him after the passage of one loop iteration?

  • 2
    With the object - nothing happens. Variable - disappears. - Pavel Mayorov

3 answers 3

It can be simplified to assume that variables declared inside a restricted block { } exist as long as the code of this block is executed. As soon as control is transferred out of the block, all local variables of the block are deleted.

With objects otherwise. The object exists as long as it can be accessed by reference. When no live links are left, the object can be deleted by the garbage collector.

In reality, the mechanism in both cases is more complicated, but for the initial understanding this is sufficient.

In your code, variables declared inside the loop will be recreated at each iteration. You put the Bitmap link in the List declared outside the loop, so nothing happens to it.

Creating an object occurs at the moment when the constructor new Bitmap(fn) called, and it should of course be inside the loop.

As for the question "how is better?" - the clearer the code, the better, in the process of work, the compiler and the Jit-compiler will still optimize and change it as they see fit and effective. Although it should be noted that for languages ​​based on the stack machine, C # among them, there is a recommendation to declare a variable as close as possible to the place of its use, i.e. if the variable is used only inside the loop iteration and its value does not participate in the subsequent iterations, we declare it inside the loop, otherwise we declare it inside the loop.

Well, spend another day on purposeful study / repetition of the foundations of the language, the principles of working with memory and garbage collection in .NET, this is really necessary, unless of course you plan to develop further in this direction. Here is an excellent list of references.

    You can do as your heart desires, but the JIT compiler optimizes your code when executed. Most likely, one variable will be created, which will be referenced by the code in the loop.

      See it.

      Bitmap bmp text Bitmap bmp declares a reference to a Bitmap object. At each iteration of the loop, you construct a new object, and the link begins to reference the object (as a result of the assignment).

      If the link is declared after the cycle, then (starting from the second iteration), the link no longer points to the old object left over from the last iteration, and it becomes an allowed garbage collector.

      If the link is declared inside the loop, then it dies at the end of each iteration, and the object again becomes accessible to the garbage collector.


      Technically, the difference is that when you declare a link by loop, the old value is still available at the beginning of the loop, and the last value is available after the loop ends. Usually, such accessibility is not necessary or even harmful: you can forget to initialize the variable, and you will work with the old object instead of the new one.

      Example:

       Bitmap bmp = null; foreach (string fn in fileNames) { if (condition) bmp = new Bitmap(fn); // else вы работаете со старым объектом } 

      If bmp declared inside, the compiler will not miss it.

      Therefore, it is usually recommended to declare variables in the nested block itself, wherever possible, to protect against stupid errors.


      Clarification: as @Zufir correctly suggests in the comment, the link to bmp stored in a bitmapsList , so the object will not be eaten by the garbage collector in this case. But without this save, the object would be available for assembly.

      • one
        "The link no longer points to the old object left over from the last iteration, and it becomes a garbage collector allowed to be assembled." And unless in the list the link to the "old object" will not be saved? - Zufir
      • one
        @Zufir: Exactly, it will continue! But this is because the link inside the loop is copied to the list. - VladD