C#在foreach循环中使用点'偏移方法来修改点数组

Ndn*_*nes 2 c# foreach point

我无法理解点的偏移方法如何在foreach循环中工作以修改现有的点数组.我能够通过手动索引每个数组实体来完成它,但我强烈怀疑它不是应该如何完成的.

*编辑要清楚.在MyPoints数组中存储偏移点的最佳方法是什么?

见下面的代码.我使用http://rextester.com/在线C#编译器来测试代码.

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*/
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 6

System.Drawing.Point是一种结构 - 一种价值类型.该foreach循环复制Point值从收集到的p变量.然后,您可以p通过调用来修改变量Offset,但这根本不会更改集合,因为它只是修改后的副本.

在第二个循环中,您将直接修改数组中的值 - 这就是您看到差异的原因.

更为惯用的做法是:

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

值得注意的是,这Point是一个相对不寻常的,因为它是一个可变的值类型 - 该Offset方法确实改变了价值.大多数值类型(例如DateTime)是不可变的 - 像AddDays不修改它们被调用的值的方法; 相反,他们返回一个值.所以要做一些与日期数组类似的东西,你需要这样的代码:

for (int i = 0; i < dates.Length; i++)
{
    dates[i] = dates[i].AddDays(10);
}
Run Code Online (Sandbox Code Playgroud)

或者您可以使用LINQ创建一个新数组:

DateTime[] newDates = dates.Select(date => date.AddDays(10)).ToArray();
Run Code Online (Sandbox Code Playgroud)

Point由于Offset返回的方式,你不能完全像那样写void.你需要这样的东西:

Point[] newPoints = points.Select(point => { point.Offset(5,2); return point; })
                          .ToArray();
Run Code Online (Sandbox Code Playgroud)

  • @thesystem我认为关键字是_copy_.我理解它的方式是p只是一个副本而不影响从中复制的内容.假设你有一个变量A,然后复制它并调用它B.改变B不会改变A.但这就是我理解它的方式而且我对C#很新,所以我肯定会验证它. (2认同)