Collections ByVal ByRef?

A

aaj

Hi all

can anyone shed a little light on to my Newbie problem?

I have written my own collection that impliements the IEnumerator/Enumerable
interfaces and on the surface, all seems well.

The problem happens while I Itterate through it using foreach

during the itteration I recursively itterate the same collection. Although
what follows is not the code I'm using, it simplifies the question I'm tring
to ask.

if I have a collection of tools in a box

foreach tool t in box
{
checkforqtyoftools(box,t.name)
}

and then I have a function that for each toot, runs through itsself again
counting the amount of times it occurs

checkforqtyoftools(collection box, tool toolname)
foreach tool t in box
{
count number of tools.name in box....
}

my collection class uses a variable 'count' to hold the position within the
collection.

The problem is, even though the default passing is byval, the inner loop is
altering the count variable of the 'box' object of the outer loop,

The obvious answer is to store the count at the beggining of the inner loop,
and set it back as it exits, but this doesn't feel like a good way to do it.

So the questions are

why does passing a collection byval to a function alow the varaibles in the
collection to be altered.
What is the best way of dealing with the problem.

many thanks

Andy

PS I know one of the answers might be you dont need to itterate int the
other loop, do it the other way... but my problem is different from the one
above, its more the principle of keeping the two collections seperate that
I'm interested in.
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Well, you do not explain your real escenario very well, so I hope this
help.

A collection is always passed by ref, therefore if you change it inside a
method it will be reflected outside, even more, if you are iterating in a
collection you should not change it, it would rise an exception.
you can change the members of the collected instances though.

where u keep the count variable? from the call to checkforqtyoftools it
seems that you keep it inside either box , or t

maybe a better way to do it is to use a hashtable, like this:

Hashtable table = new Hashtable()
foreach( tool t in box)
if ( table[ t.name] == null )
table[ t.name] =1;
else
table[ t.name] = (int)table[ t.name] + 1;


much easier and clear.


cheers,
 
A

aaj

Thanks Ignacio

I didn't realise it always passed byref (although that makes sense).

I never change the values in the 'inside itteration', only test against
them, which probably explains how I've gotten it to work so far.:cool:

I'll take a look at hashtables, and see if it works better in this case

thanks again

Andy


Ignacio Machin ( .NET/ C# MVP ) said:
Hi,

Well, you do not explain your real escenario very well, so I hope this
help.

A collection is always passed by ref, therefore if you change it inside a
method it will be reflected outside, even more, if you are iterating in a
collection you should not change it, it would rise an exception.
you can change the members of the collected instances though.

where u keep the count variable? from the call to checkforqtyoftools it
seems that you keep it inside either box , or t

maybe a better way to do it is to use a hashtable, like this:

Hashtable table = new Hashtable()
foreach( tool t in box)
if ( table[ t.name] == null )
table[ t.name] =1;
else
table[ t.name] = (int)table[ t.name] + 1;


much easier and clear.


cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation


aaj said:
Hi all

can anyone shed a little light on to my Newbie problem?

I have written my own collection that impliements the
IEnumerator/Enumerable interfaces and on the surface, all seems well.

The problem happens while I Itterate through it using foreach

during the itteration I recursively itterate the same collection.
Although what follows is not the code I'm using, it simplifies the
question I'm tring to ask.

if I have a collection of tools in a box

foreach tool t in box
{
checkforqtyoftools(box,t.name)
}

and then I have a function that for each toot, runs through itsself again
counting the amount of times it occurs

checkforqtyoftools(collection box, tool toolname)
foreach tool t in box
{
count number of tools.name in box....
}

my collection class uses a variable 'count' to hold the position within
the collection.

The problem is, even though the default passing is byval, the inner loop
is altering the count variable of the 'box' object of the outer loop,

The obvious answer is to store the count at the beggining of the inner
loop, and set it back as it exits, but this doesn't feel like a good way
to do it.

So the questions are

why does passing a collection byval to a function alow the varaibles in
the collection to be altered.
What is the best way of dealing with the problem.

many thanks

Andy

PS I know one of the answers might be you dont need to itterate int the
other loop, do it the other way... but my problem is different from the
one above, its more the principle of keeping the two collections seperate
that I'm interested in.
 
C

Christof Nordiek

Hi Andy,

if your class implements IEnumrable it has to implement the GetEnumerator
method, wich should return an IEnumerator.
That Enumerator should contain the counter not the collection, and the
Enumerator should always be a new instance.
Then there will be one counter per loop.

Christof
 
J

Jon Skeet [C# MVP]

<"Ignacio Machin \( .NET/ C# MVP \)" <ignacio.machin AT
dot.state.fl.us> said:
Well, you do not explain your real escenario very well, so I hope this
help.

A collection is always passed by ref

No it's not. "Pass by reference" and "pass reference by value" are
significantly different.

See http://www.pobox.com/~skeet/csharp/parameters.html

(I know you know the full story, Ignacio, but I don't think it helps
people to give the simplified but incorrect version.)
 

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