Passing constructor parameter by value?

C

Chris Ashley

I'm getting a little confused at the behaviour of C# with one of my
class constructors. A code example will probably help:

public class RawBitmap
{
internal BITMAPFILEHEADER fileHdr;
internal BITMAPINFOHEADER infoHdr;
private Byte[] bytImgData;

public RawBitmap(BITMAPFILEHEADER theHeader, BITMAPINFOHEADER
theInfo)
{
fileHdr = theHeader;
infoHdr = theInfo;
}

public void SetWidth(int intWidth)
{
infoHdr.biWidth = intWidth;
}
}


public class RawBitmapManager
{

private BITMAPFILEHEADER fileHdr;
private BITMAPINFOHEADER infoHdr;
public RawBitmap[] theBitmaps;

public void SetByteData()
{

// Generate standard length strips
for (int i = 0; i < intTotalStrips; i++)
{
theBitmaps = new RawBitmap(fileHdr, infoHdr);
theBitmaps.SetHeight(256);
theBitmaps.BytImgData = ReadLines(ioBinaryStream,
STRIP_HEIGHT);
}

if (intLastStripHeight > 0)
{
intTotalStrips++;
int intLastBound = theBitmaps.GetUpperBound(0);
theBitmaps[intLastBound] = new RawBitmap(fileHdr, infoHdr);
theBitmaps[intLastBound].SetHeight(11);
theBitmaps[intLastBound].BytImgData =
ReadLines(ioBinaryStream, intLastStripHeight);
}


}


RawBitmapManager holds an Array of RawBitmap objects. When I call the
'SetByteData' method I would expect the array of RawBitmaps to be
populated with copies of infoHdr, but instead it looks like it is being
passed by reference because the biHeight property of every item in the
array is set to 11 at the end of the method. If I comment out the
intLastStripHeight bit, every item int he array is set to 256.

How can I force the constructor parameters to be copied rather than
passed by reference?

Thanks,

Chris
 
M

Marc Gravell

Well, what are BITMAPFILEHEADER and BITMAPINFOHEADER? Classes? Structs? If
they are classes, then the reference will be passed by value, so yes: each
RawBitmap will be looking at the same instance of fileHdr etc.

If appropriate (and it almost always isn't) you could make these structs. I
doubt this would be a good idea. A better option may be to simply provide a
Clone() method on these objects, and explicitely clone them before passing
them to the ctor.

Marc
 
J

Jon Skeet [C# MVP]

Chris said:
I'm getting a little confused at the behaviour of C# with one of my
class constructors.

How can I force the constructor parameters to be copied rather than
passed by reference?

The parameter *is* being passed by value - but arrays are reference
types, so the parameters are references themselves. You'll need to
create a copy of the array in the constructor.

See http://www.pobox.com/~skeet/csharp/parameters.html for details of
parameter passing. (There's nothing special about constructors in this
regard.)

Jon
 
H

Hans Kesting

Well, what are BITMAPFILEHEADER and BITMAPINFOHEADER? Classes? Structs? If
they are classes, then the reference will be passed by value, so yes: each
RawBitmap will be looking at the same instance of fileHdr etc.

If appropriate (and it almost always isn't) you could make these structs. I
doubt this would be a good idea. A better option may be to simply provide a
Clone() method on these objects, and explicitely clone them before passing
them to the ctor.

Marc

Or clone then *inside* the constructor

Hans Kesting
 
H

Hans Kesting

Can you use the ref keyword to pass by reference?
I don't know if that is possible for a constructor, but it would just
pass the reference to the object by reference. It would NOT "clone" the
object or otherwise make an independant copy.

Hans Kesting
 
Top