Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# using points' offset method in foreach loop to modify array of points

Tags:

c#

foreach

point

I am having trouble understanding how points' offset method works within a foreach loop to modify an existing array of points. I am able to do it by manually indexing each array entity, but I strongly suspect that is not how it should be done.

*Edit To be clear. What is the best way to store my offset points in MyPoints array?

See code below. I used http://rextester.com/ online C# compiler to test the code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Drawing;
namespace Rextester
{
    public class Program
    {
        static int ii = 0;
        public static void Main(string[] args)
        {
            Point[] MyPoints = 
            {
                new Point(0,0),
                new Point(10,10),
                new Point(20,0)
            };

            foreach(Point p in MyPoints)
            {
                p.Offset(5,2); //this works but does not store the new points                 
            }                  //in MyPoints array when the foreach loop 
                               //exits, which is what I want.

        Console.WriteLine("p1x = {0} \t p1y = {1}", MyPoints[0].X, MyPoints[0].Y);
        Console.WriteLine("p2x = {0} \t p2y = {1}", MyPoints[1].X, MyPoints[1].Y);
        Console.WriteLine("p3x = {0} \t p3y = {1} \n", MyPoints[2].X, MyPoints[2].Y);

        foreach(Point p in MyPoints)
        {
            MyPoints[ii].Offset(5,2);
            ii++;
        }

        Console.WriteLine("p1x = {0} \t p1y = {1}", MyPoints[0].X, MyPoints[0].Y);
        Console.WriteLine("p2x = {0} \t p2y = {1}", MyPoints[1].X, MyPoints[1].Y);
        Console.WriteLine("p3x = {0} \t p3y = {1}", MyPoints[2].X, MyPoints[2].Y);
        }
    }
}
//This yields the following
/*
p1x = 0      p1y = 0
p2x = 10     p2y = 10
p3x = 20     p3y = 0 

p1x = 5      p1y = 2
p2x = 15     p2y = 12
p3x = 25     p3y = 2*/
like image 443
Ndnes Avatar asked Sep 03 '25 01:09

Ndnes


1 Answers

System.Drawing.Point is a structure - a value type. The foreach loop copies the Point value out of the collection into the p variable. You then modify the p variable by calling Offset, but that doesn't change the collection at all, because it's only the copy that's modified.

In your second loop, you're modifying the value in the array directly - which is why you're seeing the difference.

A more idiomatic way of doing that would be:

for (int i = 0; i < MyPoints.Length; i++)
{
    MyPoints[i].Offset(5, 2);
}

It's worth noting that Point is relatively unusual as it's a mutable value type - the Offset method really changes the value. Most value types (e.g. DateTime) are immutable - methods like AddDays don't modify the value they're called on; instead they return a new value. So to do something similar with an array of dates, you'd need code like this:

for (int i = 0; i < dates.Length; i++)
{
    dates[i] = dates[i].AddDays(10);
}

Or you could use LINQ to create a new array:

DateTime[] newDates = dates.Select(date => date.AddDays(10)).ToArray();

You couldn't write it exactly like that for Point because of the way Offset returns void. You'd need something like:

Point[] newPoints = points.Select(point => { point.Offset(5,2); return point; })
                          .ToArray();
like image 199
Jon Skeet Avatar answered Sep 04 '25 14:09

Jon Skeet