MyObject o = my_objects[i];
//now a second thread has set my_objects to null, and/or invoked my_objects.Remove(o)
o.myMethod();
That's fine. The variable my_objects
holds references to objects, not the objects themselves. When you make a new variable o
, it holds a second reference to the same object. Then you clear my_objects
, which means you can't refer to the actual object through my_objects
anymore. But that doesn't change the fact that you still have o
, and you can still refer to the actual object through o
. (And that in turn implies that the object itself still exists. C# is a garbage-collected language, which, to a first approximation means that objects are guaranteed to stick around until you're done with them. Non-managed C++ is different in this respect, and Objective-C is different in yet a third way. Not that you asked.)
Effectively, in this respect, references to MyObject
behave just like primitive types like int
. If I have an array of int
, and I do
int oi = my_ints[i];
then I can do whatever I want with my_ints
(clear it, remove items from it) and that won't change the fact that oi
still exists.
The thing about reference types like MyObject
, and the reason you got confused enough to ask this question, is that with MyObject
both variables (o
and my_objects[i]
) still refer to the same actual object, so if you mutate the object via my_objects[i].gainSpiderPowers()
, you'll see the effects of that mutation no matter whether you're looking via my_objects[i]
or via o
.