Search code examples
c#foreachiteratorprimitive

How to change the value of a primitive data type variable referred to by a foreach iterator


If I have a class Ball with a set accessor for its property radius, I can set the radius of a list of Ball objects using a foreach loop:

foreach(Ball ball in balls)
{
    ball.radius = 1;
}

But if I am iterating through a collection of primitive data types, this does not work because the primitive does not have accessors. If I try to change the value of the primitive data type, I am actually performing the operation on the iterator, not to value itself, so the following does not work:

foreach(double radius in radii)
{
    radius = 1;
}

I tried solving it with a pointer, like this:

double* p;
foreach(double radius in radii)
{
    p = &radius;
    *p = 1;
}

Unsurprisingly, this does not work because p refers to the address occupied by the iterator, not the variable.


In case it is important here, I will be more specific about what I am actually trying to do, and although I would still like an answer to my main question, it's quite possible that there is a much simpler way to do this with the methods of List<>, which I am not too familiar with. I have a List<List<double>>, which I want to alter every element of, specifically by dividing each by a normalisation constant normalisationFactor. The following works perfectly:

for (int i = 0; i < array.Count; i++)
{
    for (int j = 0; j < array[0].Count; j++)
    {
        array[i][j] /= normalisationFactor;
    }
}

However, I find the foreach syntax much more readable, and would like to to it that way if I can. For the reasons I have detailed above, the following does not work:

foreach (List<double> row in array)
{
    foreach (double value in row)
    {
        value /= normalisationFactor;
    }
}

So, how do I achieve what I want using a foreach loop?


Solution

  • primitives (structs) are immutable and passed around as values not pointers.

    IEnumerables do not provide an means to update the data.

    If you know the underlining data type (Array, Collection, List), just loop the position index and update the collection position

    for (var i=0; i < radius.Count; i++)
        radius[i] = newValue