tags:

views:

161

answers:

4

How can I add an item to a list if that item is essentially a pointer and avoid changing every item in my list to the newest instance of that item?

Here's what I mean:
I am doing image processing, and there is a chance that I will need to deal with images that come in faster than I can process (for a short period of time). After this "burst" of images I will rely on the fact that I can process faster than the average image rate, and will "catch-up" eventually.

So, what I want to do is put my images into a <List> when I acquire them, then if my processing thread isn't busy, I can take an image from that list and hand it over.

My issue is that I am worried that since I am adding the image "Image1" to the list, then filling "Image1" with a new image (during the next image acquisition) I will be replacing the image stored in the list with the new image as well (as the image variable is actually just a pointer).

So, my code looks a little like this:

while (!exitcondition)
{
    if(ImageAvailabe())
    {
       Image1 = AcquireImage();
       ImgList.Add(Image1);
    }
    if(ImgList.Count > 0)
    {
       ProcessEngine.NewImage(ImgList[0]);
       ImgList.RemoveAt(0);
    }
}

Given the above, how can I ensure that:
- I don't replace all items in the list every time Image1 is modified.
- I don't need to pre-declare a number of images in order to do this kind of processing.
- I don't create a memory devouring monster.

Any advice is greatly appreciated.

+1  A: 

Your code is correct. None of your above code affects previously added images. The line:

Image1 = AcquireImage();

puts the reference (to an image) returned from AcquireImage into the Image1 reference variable. Then:

ImgList.Add(Image1);

adds that reference to your list. Changing your Image1 reference variable does not affect references already in the list.

Matthew Flaschen
Ah, so `list` doesn't just point to the location of the instance, but instead it actually allocates the memory separately?Somehow I can never quite understand how C# does things... Thanks for the insight!
Gorchestopher H
@Gorchestopher: It modifies the Image1 *variable* - but changing that variable's value won't change anything in the list.
Jon Skeet
It's setting Image1 to a reference to a new image. But the list still holds a reference to the old one.
Matthew Flaschen
Jon, unless Image1 is mutable and AcquireImage is writing over it (meaning it must be a field). But I don't think that's the case.
Matthew Flaschen
What was confusing me was a previous problem I had when I did something like:<pre>Image1 = AcquireImage();Image2 = Image1;Image2.Dispose()</pre>And suddenly Image1 was null.
Gorchestopher H
That's because Image1 and Image2 reference the same object (though it would be disposed, not null) in that example. Similarly, in this case, the list and temporary momentarily have references to the same object. Then the temporary instead gets a reference to a new one, but the list still has references to all the old ones.
Matthew Flaschen
+2  A: 

Just reinitialize:

Replace

Image1 = AcquireImage();

with

Image1 = new Image(AcquireImage());

or just say

ImageList.Add(new Image(AcquireImage()));
smoore
Ah, so in doing this the old instance of Image1 inside ImgList be preserved?
Gorchestopher H
+1, this is correct. Don't forget to call Dispose() on the image object when you're done processing it.
Hans Passant
This is only necessary if AcquireImage is repeatedly modifying the same image object in place.
Matthew Flaschen
A: 

Conceptually, your code will be fine. The important element is that AcquireImage() allocates a new instance for each incoming image.

If Image1 were a pointer, you would have a problem - however a C# reference is not a pointer.

Steven Mackenzie
I don't agree. The same concept would apply to a list of pointers.
Matthew Flaschen
I was a little hasty with that comment. I was trying to anticipate what the OP might have meant when referring to a reference as a pointer, and ended up with a double pointer (or a theoretical boxed, mutable pointer).
Steven Mackenzie
A: 

If I understand what you're saying correctly, you want to be able to re-use a variable without overwriting its existing data. The good news is that you don't need to change anything. You're partially correct when you say that Image1 is a pointer: it's a reference to whichever image it's pointing to at the time. When you allocate it:

Image1 = AcquireImage();

you're not overwriting the contents of the existing image, but changing the reference so it points to the new image. Assuming AcquireImage is working correctly and returns a new image every time, rather than overwriting the previous one, the above code will discard the existing reference in favour of the new one. However, as you've added it to the list already, a reference to the image is retained somewhere in your code, and so it will not be lost.

Samir Talwar