Indexers: what am I doing wrong?

E

Enkidu

Beginner question, sorry!

I am using indexers to access an array of StringBuilders in an instance
of a class:

Getting:
value = board1;
Setting:
board1[j] = value1 ;

I loop through the array in the main program using the above to get/set
the members of the array. I find that some of the StringBuilders in the
array are suddenly being set to the same value!

To explain a bit further, while debugging I watch the values in the
array, and when I am processing element 12 for example, elements 13, 14,
15 are set to the same value that I set element 12 to.

What might I be running into? Garbage collection? Thread issues?

Cheers,

Cliff
 
J

Jon Skeet [C# MVP]

Enkidu said:
Beginner question, sorry!

I am using indexers to access an array of StringBuilders in an instance
of a class:

Getting:
value = board1;
Setting:
board1[j] = value1 ;

I loop through the array in the main program using the above to get/set
the members of the array. I find that some of the StringBuilders in the
array are suddenly being set to the same value!

To explain a bit further, while debugging I watch the values in the
array, and when I am processing element 12 for example, elements 13, 14,
15 are set to the same value that I set element 12 to.

What might I be running into? Garbage collection? Thread issues?


Well, you haven't shown the code for the indexer, which means we're
guessing really.

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.
 
E

Enkidu

Jon said:
Enkidu said:
Beginner question, sorry!

I am using indexers to access an array of StringBuilders in an instance
of a class:

Getting:
value = board1;
Setting:
board1[j] = value1 ;

I loop through the array in the main program using the above to get/set
the members of the array. I find that some of the StringBuilders in the
array are suddenly being set to the same value!

To explain a bit further, while debugging I watch the values in the
array, and when I am processing element 12 for example, elements 13, 14,
15 are set to the same value that I set element 12 to.

What might I be running into? Garbage collection? Thread issues?


Well, you haven't shown the code for the indexer, which means we're
guessing really.

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.

Well, it's difficult to know which bits to choose. I've not actually run
the following, since I don't know which bits are relevant (yeah, I did
look at the URL, and yeah, I know I haven't totally complied)

It's pretty simple though. Here's the 'Board' class. Bits omitted but
not from these methods.

namespace Blahblah
{

public class Board
{
private StringBuilder[] grid;

public Board()
{
grid = new StringBuilder[81];
for (int i = 0; i < 81; i++)
{
grid = new StringBuilder("123456789", 9);
}
}


public StringBuilder this[int index]
{
get
{
return grid[index];
}
set
{
grid[index] = value;
}
}
}

Here's the main program:

namespace Blahblah
{
// static class Program
class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
// Read a file
public static Program pgm;
public static Board board1;
public static Form1 myForm;

[STAThread]
static void Main()
{
pgm = new Program();
board1 = pgm.getBoard();
// Form stuff omitted..
}
// Stuff omitted.
public void processGrid()
{
StringBuilder value = new StringBuilder() ;
StringBuilder value1 = new StringBuilder() ;
...
value.Length = 0; // Set Length to 0 ;
value.Append( board1[index].ToString() ) ;
...
while (true)
{
...
value1.Length = 0 ;
value1.Append( board1[ (line * 9) + j ].ToString() ) ;
...
}
}
}
}

Cheers,

Cliff
 
P

Peter Duniho

Well, it's difficult to know which bits to choose. I've not actually run
the following, since I don't know which bits are relevant (yeah, I did
look at the URL, and yeah, I know I haven't totally complied)

You didn't post any code that actually sets the indexed value. All of the
uses are just gets. Nor did you post code that would actually compile and
run. Please re-read Jon's post, and the link he refers you to, regarding
"a short but complete program".

That said, your indexer looks pretty simple...it seems hard to believe
that it is actually involved in the problem. My guess is that you could
replace the class with a simple StringBuilder[] array and you'd have the
same problem. And since you didn't post the code with the problem, it's
impossible for anyone to point out the mistake.

Pete
 
E

Enkidu

Peter said:
Well, it's difficult to know which bits to choose. I've not actually
run the following, since I don't know which bits are relevant (yeah, I
did look at the URL, and yeah, I know I haven't totally complied)

You didn't post any code that actually sets the indexed value. All of
the uses are just gets. Nor did you post code that would actually
compile and run. Please re-read Jon's post, and the link he refers you
to, regarding "a short but complete program".

That said, your indexer looks pretty simple...it seems hard to believe
that it is actually involved in the problem. My guess is that you could
replace the class with a simple StringBuilder[] array and you'd have the
same problem. And since you didn't post the code with the problem, it's
impossible for anyone to point out the mistake.
Yes, I know I didn't post a 'working' program, but is this bit not
setting an indexed value? If so, that may be part of my problem.

board1[ (line * 9) + j ] = value1 ;

Yes, I am prepared to do the work and create a 'working' program, but my
difficulty is that, as a beginner, even the simplest things can block me
for ages, whereas a seasoned pro would immediately know what was wrong.
(Sort of like Expert: "You've jiggled the parsnips, but you should have
woggled 'em". Me: "Eh??"). I hoped that this would be the case. It's a
hard life on the steep bit of the learning curve!

Oh well, off to do a bit of coding....

Cheers,

Cliff
 
E

Enkidu

Enkidu said:
Peter said:
Well, it's difficult to know which bits to choose. I've not actually
run the following, since I don't know which bits are relevant (yeah,
I did look at the URL, and yeah, I know I haven't totally complied)

You didn't post any code that actually sets the indexed value. All of
the uses are just gets. Nor did you post code that would actually
compile and run. Please re-read Jon's post, and the link he refers
you to, regarding "a short but complete program".

That said, your indexer looks pretty simple...it seems hard to believe
that it is actually involved in the problem. My guess is that you
could replace the class with a simple StringBuilder[] array and you'd
have the same problem. And since you didn't post the code with the
problem, it's impossible for anyone to point out the mistake.
Yes, I know I didn't post a 'working' program, but is this bit not
setting an indexed value? If so, that may be part of my problem.

board1[ (line * 9) + j ] = value1 ;

Yes, I am prepared to do the work and create a 'working' program, but my
difficulty is that, as a beginner, even the simplest things can block me
for ages, whereas a seasoned pro would immediately know what was wrong.
(Sort of like Expert: "You've jiggled the parsnips, but you should have
woggled 'em". Me: "Eh??"). I hoped that this would be the case. It's a
hard life on the steep bit of the learning curve!

Oh well, off to do a bit of coding....
Um, can someone advise - the line that follows:

board1[ (line * 9) + j ] = value1 ;

Does this copy the contents of the object 'value1' to the object
'board1[ (line * 9) + j ]' or does it set the object reference of
'board1[ (line * 9) + j ]' to the object reference of 'value1'?

Cheers,

Cliff
 
J

Jon Skeet [C# MVP]

Um, can someone advise - the line that follows:

board1[ (line * 9) + j ] = value1 ;

Does this copy the contents of the object 'value1' to the object
'board1[ (line * 9) + j ]' or does it set the object reference of
'board1[ (line * 9) + j ]' to the object reference of 'value1'?

The latter. It's copying the value of "value1" - which is just a
reference to an object.
 
E

Enkidu

Jon said:
Um, can someone advise - the line that follows:

board1[ (line * 9) + j ] = value1 ;

Does this copy the contents of the object 'value1' to the object
'board1[ (line * 9) + j ]' or does it set the object reference of
'board1[ (line * 9) + j ]' to the object reference of 'value1'?

The latter. It's copying the value of "value1" - which is just a
reference to an object.
Ah, then that is probably my prob, thanks,

Cheers,

Cliff
 
E

Enkidu

Enkidu said:
Jon said:
Enkidu said:
Oh well, off to do a bit of coding....
Um, can someone advise - the line that follows:

board1[ (line * 9) + j ] = value1 ;

Does this copy the contents of the object 'value1' to the object
'board1[ (line * 9) + j ]' or does it set the object reference of
'board1[ (line * 9) + j ]' to the object reference of 'value1'?

The latter. It's copying the value of "value1" - which is just a
reference to an object.
Ah, then that is probably my prob, thanks,
Thanks Jon, that *was* my problem!!

I changed it to:

board1[(line * 9) + j].Length = 0;
board1[(line * 9) + j].Append(value1.ToString());

That appears to work, though it may not be the best or preferred way!

Cheers,

Cliff
 
P

Peter Duniho

Enkidu said:
Yes, I know I didn't post a 'working' program, but is this bit not
setting an indexed value? If so, that may be part of my problem.

board1[ (line * 9) + j ] = value1 ;

Maybe I'm blind, but I don't see that line of code in the code you posted.
Yes, I am prepared to do the work and create a 'working' program, but my
difficulty is that, as a beginner, even the simplest things can block me
for ages, whereas a seasoned pro would immediately know what was wrong.

Even a seasoned pro cannot tell you what's wrong in code that you don't
post.

Beyond that, part of relying on a seasoned pro to point out your own
mistake rather than figuring it out yourself is to do as asked when a
seasoned pro asks you to formulate your question in a way that will
facilitate answering it. Not only will doing so help _you_, it avoids
having the seasoned pro dismiss your question due to lack of cooperation
on your part.

Finally, one very important part about coming up with an actual
concise-but-complete sample of code that reliably reproduces the problem
is that in refactoring your existing code to remove the irrelevant parts
is often sufficient for figuring out the problem yourself. The exercise
itself can either make the bug more apparent, or cause it to go away
when you take out some piece of the code, the latter being a very good
indication to you of what piece of the code is causing problems.

And I will note that that last paragraph does not apply only to
beginners. Just the other day, I had a problem in my code that was
causing me no end of frustration (it was related to the behavior of the
XmlReader class). I was just about to post a question here, and was
preparing my concise-but-complete code sample, when the bug in my code
revealed itself. The mere process of creating a question that was
actually appropriate to ask helped me solve my problem all by myself.

Now, all that said:

If the line of code that you posted alone in your reply is inside the
while() loop and you do not create a new StringBuilder to assign to
value1 each time through the loop, then that's your problem right there.
You are assigning the same StringBuilder to each element, and so any
time you change that one StringBuilder, changes to it are of course
reflected in each indexed element that was assigned to it.

Pete
 
E

Enkidu

Peter said:
Enkidu said:
Yes, I know I didn't post a 'working' program, but is this bit not
setting an indexed value? If so, that may be part of my problem.

board1[ (line * 9) + j ] = value1 ;

Maybe I'm blind, but I don't see that line of code in the code you
posted.
OK, it was intended and if it wasn't there, mea culpa.
Even a seasoned pro cannot tell you what's wrong in code that you
don't post.
Absolutely. But the *symptom* may be indicative of a particular type of
error. I was looking for a quick answer, but if the quick answer is not
appropriate (as you have indicated), I'm quite prepared to do the work.
Beyond that, part of relying on a seasoned pro to point out your own
mistake rather than figuring it out yourself is to do as asked when
a seasoned pro asks you to formulate your question in a way that will
facilitate answering it. Not only will doing so help _you_, it
avoids having the seasoned pro dismiss your question due to lack of
cooperation on your part.
I did figure it out myself! In hindsight a problem with lots of
variables changing at once almost HAS to be a reference problem.
Finally, one very important part about coming up with an actual
concise-but-complete sample of code that reliably reproduces the
problem is that in refactoring your existing code to remove the
irrelevant parts is often sufficient for figuring out the problem
yourself. The exercise itself can either make the bug more apparent,
or cause it to go away when you take out some piece of the code, the
latter being a very good indication to you of what piece of the code
is causing problems.
Yes indeed, no argument, and that is what I went on to do.
And I will note that that last paragraph does not apply only to
beginners. Just the other day, I had a problem in my code that was
causing me no end of frustration (it was related to the behavior of
the XmlReader class). I was just about to post a question here, and
was preparing my concise-but-complete code sample, when the bug in my
code revealed itself. The mere process of creating a question that
was actually appropriate to ask helped me solve my problem all by
myself.
Yes, it often happens that way.
Now, all that said:

If the line of code that you posted alone in your reply is inside the
while() loop and you do not create a new StringBuilder to assign to
value1 each time through the loop, then that's your problem right
there. You are assigning the same StringBuilder to each element, and
so any time you change that one StringBuilder, changes to it are of
course reflected in each indexed element that was assigned to it.
That's exactly what the problem was! I'd already figured it out, but
thanks!

Cheers,

Cliff
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top