Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么更改结构中的数组时所有引用都会更改?_C#_List - Fatal编程技术网

C# 为什么更改结构中的数组时所有引用都会更改?

C# 为什么更改结构中的数组时所有引用都会更改?,c#,list,C#,List,我正在从事C#项目,我的代码是这样的: public struct Point { public int X; public int[,] arr; } List<Point> po=new List<Point>(); void func() { Point p1; p1.arr = new int[1, 1]; p1.X = 10; p1.arr[0, 0] = 1; func2(p2); p1.X=20

我正在从事C#项目,我的代码是这样的:

public struct Point
{
    public int X;
    public int[,] arr;
}
List<Point> po=new List<Point>();
void func()
{
    Point p1;
    p1.arr = new int[1, 1];
    p1.X = 10;
    p1.arr[0, 0] = 1;
    func2(p2);
    p1.X=20;
    p1.arr[0,0]=10;
 }
void func2(Point h)
    {
        po.Add(h);
    }
void func2(ref Point po, Point h){
    po.Add(h);
}
公共结构点
{
公共int X;
公共国际[,]arr;
}
列表po=新列表();
void func()
{
p1点;
p1.arr=新整数[1,1];
p1.X=10;
p1.arr[0,0]=1;
功能2(p2);
p1.X=20;
p1.arr[0,0]=10;
}
第2点(h点)
{
po.Add(h);
}

当我跟踪此代码并从func2返回时,当更改p1.x时,列表中的我的点(x参数)未更改,但当更改p1.arr为10时,列表中的我的点(arr参数)也从1更改为10。为什么会发生这种情况?如何解决此问题?

结构具有值语义。这意味着更改p1.x就是更改一个值,而不是一个引用。您有一个正在更改的本地值p1。更改数组中的值时,就是更改该值的副本。

结构是C#中的值类型,而类是引用。尝试使用ref修改器将点传递到func2

void func2(ref Point h){
    ....
}
实际上,多亏了SD中的JG,它应该更像这样:

public struct Point
{
    public int X;
    public int[,] arr;
}
List<Point> po=new List<Point>();
void func()
{
    Point p1;
    p1.arr = new int[1, 1];
    p1.X = 10;
    p1.arr[0, 0] = 1;
    func2(p2);
    p1.X=20;
    p1.arr[0,0]=10;
 }
void func2(Point h)
    {
        po.Add(h);
    }
void func2(ref Point po, Point h){
    po.Add(h);
}
进一步审查,这仍然是错误的。基本上,当您将点添加到列表中时,它会将逐点值复制到列表中

p1和po.Last()的值相同,但引用的对象不同。如果Point是一个类,你就不会有这个问题

您可以在将p1添加到po后立即执行此操作,但这既愚蠢又笨拙:

po.Add(p1);
var len = po.Count;
po[len-1].X = 20;
po[len-1].arr[0,0]=10;
你不能这样做:

po.Add(p1);
var len = po.Count;
var pNew = po[len-1]; 
// p1 and pNew are different objects in memory, but with the same values
pNew.X = 20;
pNew.arr[0,0]=10;
从技术上讲,你可以做到这一点,但因为它们在内存中是不同的对象,所以它不会达到你的期望


只要切换到一个类,除非您非常需要这样做。

在我看来,您只是在向列表对象添加一个值……p2从何而来?打字错误?哦-你到底想在这里做什么?是否将一个数组的值添加到列表对象?您的代码非常混乱。
p1.x
来自哪里?你的意思是
p1.X
?很明显,这个问题与不理解值类型和引用类型之间的区别有关,但我们都无法理解你真正想要做什么。代码使它看起来像是一个确定值/引用类型如何工作的练习。这不会像您所想的那样工作,因为值不是通过引用传递到
列表的。添加
@JGinSD:这是因为给定的代码首先不会编译。阿宝来自哪里?我假设应该有第二个点参数po,它应该作为ref传入,而h不应该。更新我的答案以反映这一点。谢谢。据我所知,
po
是在
func
之前声明的成员变量。但是潜在的问题仍然存在,在将
结构添加到列表后对其所做的任何更改都不会反映在
列表
中的实例上,因为没有
列表。添加(ref T item)
函数。我错过了po的声明位置。你说得对。如果这个问题能得到很好的澄清会有帮助的。谢谢你的回答,但我的问题是:虽然结构是值语义的,但当p1.x改变时,这是正确的,保存在列表中的点没有发生任何事情,这就是我想要的,但当p1.arr改变为任何东西时,列表中的arr也会更改,这是我不想要的。似乎列表中保存了对该点的引用,这对我的程序不好。