使用C#中的偏移量方法,在foreach循环中修改点数组。

3
我不太明白如何在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*/

你有什么问题吗?你说了几件事情,但实际上并没有问任何问题。 - Daxtron2
1
好的。我编辑了我的问题。谢谢。 - Ndnes
1个回答

7

System.Drawing.Point 是一个结构体,是值类型。在 foreach 循环中,将 Point 的值从集合中复制到变量 p 中。然后通过调用 Offset 修改变量 p,但这并不会改变集合,因为只有 副本 被修改了。

在第二个循环中,您直接修改了数组中的值,这就是为什么您看到了差异的原因。

更常见的做法是:

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

值得注意的是,Point 相对不太常见,因为它是一种可变的值类型 - Offset 方法会真正改变该值。大多数值类型(例如 DateTime)都是不可变的 - 像 AddDays 这样的方法不会修改调用它们的值,而是返回一个新的值。因此,要对日期数组执行类似的操作,您需要像下面这样编写代码:
for (int i = 0; i < dates.Length; i++)
{
    dates[i] = dates[i].AddDays(10);
}

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

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

由于Offset返回void,所以您无法像这样完全编写Point。 您需要类似以下内容:

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

我不是 OP,但你能否详细说明为什么第一个 foreach 循环不会改变集合,因为它修改了变量?你写得很清楚,但我仍然不完全理解。 - thesystem
好的。这非常有帮助,回答了我的问题。谢谢! - Ndnes
2
@thesystem 我认为关键字是_copy_。我的理解是p只是一个副本,不会影响被复制的内容。比如你有一个变量A,然后复制一份并将其命名为B。改变B不会改变A。但这只是我的理解,我对C#非常陌生,所以我肯定要验证一下。 - Ndnes
@Ndnes,您的解释很合理。谢谢! - thesystem
1
@thesystem:我添加了一半的句子以帮助澄清。(是的,确实是因为这是一份副本。) - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接