6

I am having a little C# beginner problem. But I'm pretty sure that it is easy to solve.

foreach(var test in Tests)
{
     object testObj = new object();             
     //Do something with the object
}

If i do it like that, the object testObj gets overwritten everytime i go through the loop. Is it possible to don't overwrite it everytime? Or do I have to use an array?

Edit: Ok sorry, I'll try to be more specific: My goal is that I create some objects in this loop and then I call a new thread with every object. There I want to do something with the object and when I'm done I'd like to release it.

Edit2 for Thomas:

foreach (var test in Tests)
{
     object testObj = new object();
     //Set some properties of the object
     Thread t = new Thread(() => manager(testObj));  
     t.Start();
}

public void manager(object testObj)
{
    //Do something with the object

    //Release it
}
xileb0
  • 451
  • 2
  • 6
  • 18
  • you want to create objects in different names> – Sajeetharan Nov 20 '15 at 07:18
  • 2
    yes it is possible, be more specific what's the problem you are facing? – Ehsan Sajjad Nov 20 '15 at 07:18
  • why you need creation of objects inside array? – Andrew Nov 20 '15 at 07:18
  • Well, that depends on what you are trying to do with this object within your loop. – MakePeaceGreatAgain Nov 20 '15 at 07:18
  • It is possible, but can you be more specific what you trying to achieve – Avinash Jain Nov 20 '15 at 07:18
  • Do you want to get single one, or all of them? In the latter, yes, you have to use a collection. To get single one, you just have to move the declaration outside of the loop, and assign value in the loop. – Paweł Mach Nov 20 '15 at 07:18
  • Ok sorry, I'll try to be more specific: My goal is that I create some objects in this loop and then I call a new thread with every object. There I want to do something with the object and when I'm done I'd like to release it. – xileb0 Nov 20 '15 at 07:26
  • @xileb0 do these objects have a dispose functionality? – Thomas Nov 20 '15 at 07:27
  • They don't. But shouldn't to that C# automatically when I don't use them anymore? – xileb0 Nov 20 '15 at 07:28
  • @xileb0 normally yes only the garbage collector does not free them immediately (important to keep in mind). there are ways to circumvent this (a feew questions on here are about that). Also some objects like specific image objects are problematic there and there are additional steps that need to be taken in order for the garbage collector to free them (ran into those problems a few time and always asked myself only one question "WHY??? :´(" .... never understood why c# is there a bit inconsistent with what you need to do ) – Thomas Nov 20 '15 at 07:31
  • example on what I mean: http://stackoverflow.com/questions/5838608/net-and-bitmap-not-automatically-disposed-by-gc-when-there-is-no-memory-left the Bitmap images – Thomas Nov 20 '15 at 07:34

2 Answers2

7

Your problems are two fold.

  1. Lifespan of the variable. A local variable only lives in the block it is defined in. Thus you defined testObj inside the foreach loop. Thus it only lives through one iteration of the block and ends to live at the end of the loop. The next iteration has a new testObj then.

Thus

object testObj 

foreach(var test in Tests)
{
     testObj = new object();             
     //Do something with the object
}

Would solve this as testObj is defined outside the loop and thus regardless of iteration lives with the values set.

Then

  1. You always set it anew. If you set a variable to a new value the old value is overwritten with the new value. Thus you would have to use lists, arrays, ... if you want to save every testObj you create (or use 1 variable for each testObj but normally that is something only complete beginners do. Only mentioning it for completeness sake and to mention that it is something not to do as it will enlarge your overhead greatly).

So you could do:

List testObjList = new List();

foreach (var tests in Tests)
{
    testObjList.Add(new object());
    // Or alternatively  object testObj = new object();  testObjList.Add(testObj);
}

If you add it directly into the list (Add(new object)) you can acces it by using testObjList[testObjList.Count - 1] (count-1 as indexes begin with 0 and not 1). This is then the same as when you use testObj of the second variant.

Edit: For using them inside threads and then eliminating these objects you have 2 options.

1.) The object does not have any functionality for dispose then your original code is fine there:

foreach(var test in Tests)
{
     object testObj = new object();             
     //Do something with the object
}

The object is lost when the block ends BUT the garbage collector decides when it is really deleted (there are some exceptions like images where it can be that you need to do special operations in order to be able to delete them though).

If your object is of a specific class (lets call it myobject to not confuse it with the normal object) that has a dispose functionality it offers:

foreach(var test in Tests)
{
     using (myObject testObj = new myObject())
     {             
         //Do something with the object
     }
}

This means that the myObject object is only living within the using block and additionally when the block ends (even if through an exception) the dispose part is executed, which should make sure that the garbage collector is able to free the memory.

Thomas
  • 2,886
  • 3
  • 34
  • 78
  • I don't think that my original code is fine :( Because somehow the first object gets always lost when I go a second time through the loop. – xileb0 Nov 20 '15 at 07:34
  • @xileb0 see problem number 1 that is the life span of the variable. If you define a variable inside a block it is only valid / living through the blocks execution once and then gets recreated (in case of a loop block). https://msdn.microsoft.com/en-us/library/aa691170(v=vs.71).aspx a bit on that topic. – Thomas Nov 20 '15 at 07:35
  • Ok i understand what you mean, but is there a way to solve this problem without an array/list? I don't have an dispose functionality btw. – xileb0 Nov 20 '15 at 07:37
  • from how I understand what you want to do is: Create a new object inside the loop then use it INSIDE the loop for a thread that is run and then reate the next object. Is that correct so? If so then your original code is just fine as the variable still has a reference set to the original address it had in memory (in the thread where you gave it as a parameter). Thus it would still live on inside the thread while in the original loop the variable with that name is set to a new value (not affecting the value you have inside the thread). – Thomas Nov 20 '15 at 07:57
  • Check my new edit pls. That is exactly what I want to do. So I'd like to have for example 20 threads and everyone of them does something with a specific object. I think you understood it wrong. You thought I always only want to work with one object at the same time. – xileb0 Nov 20 '15 at 08:03
  • nope understood you correctly there. as in my comment that should work just fine. The object you give is passed by reference: http://stackoverflow.com/questions/12997635/object-passed-as-parameter-to-another-class-by-value-or-reference whch means changes made to the object itself are consistent inside and outside. In your case the setting of a variable to a new value in the next loop does not affect the object that is used inside the thread. At the moment the end block is reached you can think of them as two different objects. – Thomas Nov 20 '15 at 08:13
  • The one that is created at the next loop is different from the object that was part of the prior loop (and is still existing inside the thread). – Thomas Nov 20 '15 at 08:13
  • So you say this should work? Interesting, because somehow it does not :/ – xileb0 Nov 20 '15 at 08:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/95660/discussion-between-thomas-and-xileb0). – Thomas Nov 20 '15 at 08:16
  • Our attempts did not change anything, still the same problem... :/ – xileb0 Nov 20 '15 at 09:16
  • @xileb0 Just recognized something. a possibility. You use .instance in the code you sent me in chat. the .instance is that static (a static variable or method or a method returning a static variable)? – Thomas Nov 20 '15 at 09:54
  • What I like about this answer is it not only answers OP, but it also answered my question about when the object gets disposed when created inside a loop, at the next iteration. Thank you! – MZawg Feb 26 '19 at 16:49
3

It is perfectly OK to create new instances of your object with every iteration as the object IS only needed for the lifetime of one single life-cycle. Thus every thread you create gets its own instance of your testObj. If you´d want to do anything with the object AFTER the loop you have to cache it, either every instance by using an array or a list or only the last instance by using object testObject BEFORE the loop and assign it with every iteration new. This however will lead to the reference testObject containing only the last instance you created within the last iteration.

object testObj;
foreach (var test in Tests)
{
     testObj = new object();  // creates a new instance every iteration
     //Set some properties of the object
     Thread t = new Thread(() => manager(testObj));  
     t.Start();
}

// do anything with the lastly created instance
DoSomething(testObject);
MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111