为什么这在C ++中有效但在C#中无效?

编程入门 行业动态 更新时间:2024-10-23 06:30:09
本文介绍了为什么这在C ++中有效但在C#中无效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

//捣乱我 - 运行它,在你克服了震惊之后 - 尝试解释它。我问过MSDN,他们投降了。

使用系统; 使用 System.Collections.Generic; 使用 System.Linq; 使用 System.Text; 使用 System.Threading.Tasks; namespace ArrayIt { class arrayit { public int i; public int j; public struct ytimeframe { public int ytime; } public struct xevents { public int id; public ytimeframe [] xy_array; } public xevents [] xevents_array; 静态 void Main( string [] args) { new arrayit()。Mainline(); } void Mainline() { i = 0 ; j = 0 ; xevents_array = new xevents [ 5 ]; // define for (j = 0 ; j < 5 ; j ++) xevents_array [j] .xy_array = new ytimeframe [ 5 ]; // define for (j = 0 ; j < 5 ; j ++) xevents_array [ 0 ]。xy_array [j] .ytime = j; // define xevents_array [ 0 ]。id = 0 ; // initialize for (i = 1 ; i < 5 ; i ++) // initialize { xevents_array [ i] = xevents_array [ 0 ]; xevents_array [i] .id = i; } Console.WriteLine( Before); for (i = 0 ; i < ; 5 ; i ++) for (j = 0 ; j < 5 ; j ++) Console.WriteLine(xevents_array [i] .id + + xevents_array [i] .xy_array [j ] .ytime); xevents_array [ 0 ]。id = 454 ; xevents_array [ 0 ]。xy_array [ 0 ]。ytime = 454 ; // 注意硬编码索引 Console.WriteLine( 在)之后; // 请说明结果 (i = 0 ; i < 5 ; i ++) for (j = 0 ; j < 5 ; j ++) Console.WriteLine(xevents_array [i] .id + + xevents_array [i] .xy_array [j] .ytime); while (Console.Read()!= ' q'); } } }

控制台输出:

在之前 0 0 0 1 0 2 0 3 0 4 1 0 1 1 1 2 1 3 1 4 2 0 2 1 2 2 2 3 2 4 3 0 3 1 3 2 3 3 3 4 4 0 4 1 4 2 4 3 4 4 之后 454 454 454 1 454 2 454 3 454 4 1 454 1 1 1 2 1 3 1 4 2 454 2 1 2 2 2 3 2 4 3 454 3 1 3 2 3 3 3 4 4 454 4 1 4 2 4 3 4 4

解决方案

什么震撼?它做了我所期望的。 你的 xevents 是一个结构 - 这意味着它是一个值类型。 它包含一个ytimeframe ojbects数组,其中 因为它是一个数组 是一个引用类型,无论它是一个数组的对象类型。 所以当你这样做时:

for (i = 1 ; i < 5 ; i ++) // initialize { xevents_array [i] = xevents_array [ 0 ]; xevents_array [i] .id = i; }

使用值类型赋值来复制xecevent_array的各个成员 - 它将对ytimeframe对象的相同数组的引用复制到每个xevents实例中。 因此,当你修改xy_array的任何元素时,你修改了xevents_array中所有实例中的相同元素。

问题出在这一行: xevents_array [i] = xevents_array [ 0 ];

您正在复制位于 0 位置的 xevents 结构对数组中每个元素的值。但是,这是浅副本。由于 struct 包含引用类型( xy_array 数组),因此每个结构的副本将指向相同的数组实例。 当您更改数组实例中的值时第一项,所有其他项目都更新,因为他们正在查看相同的数组实例。 更简单的问题演示:

静态 void Main() { Foo x = new Foo(); x.Bar = new int [ 1 ]; x.Bar [ 0 ] = 1 ; Foo y = x; y.Bar [ 0 ] = 42 ; Console.WriteLine(x.Bar [ 0 ]); // 输出为42 } public struct Foo { public int [] Bar; }

要解决此问题,您需要克隆阵列:

// xevents_array [i] = xevents_array [0]; xevents_array [i] .xy_array =(ytimeframe [])xevents_array [ 0 ]。xy_array.Clone();

编辑:我刚才意识到我只解释了为什么它不能像你期望的那样在C#中工作,我不知道为什么它在C ++中有所不同 / edit 您在 xevents_array 1-4中替换对单个 xy_arrays 的引用在这里引用 xy_array xevents_array 0:

for (i = 1 ; i < 5 ; i ++) { xevents_array [i] = xevents_array [ 0 ]; // < - here xevents_array [i] .id = i; }

所以在第一个WriteLine-Loop之前你已经看到来自同一个 xy_array 并且因此你将所有零 0-index中的一个零改为454:

xevents_array [ 0 ]。xy_array [ 0 ]。ytime = 454 ;

//riddle me this - run it and after you get over your shock - try to explain it. I've asked MSDN and they surrendered.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ArrayIt { class arrayit { public int i; public int j; public struct ytimeframe { public int ytime; } public struct xevents { public int id; public ytimeframe[] xy_array; } public xevents[] xevents_array; static void Main(string[] args) { new arrayit().Mainline(); } void Mainline() { i = 0; j = 0; xevents_array = new xevents[5]; //define for (j = 0; j < 5; j++) xevents_array[j].xy_array = new ytimeframe[5]; //define for (j = 0; j < 5; j++) xevents_array[0].xy_array[j].ytime = j; //define xevents_array[0].id = 0; //initialize for (i = 1; i < 5; i++) //initialize { xevents_array[i] = xevents_array[0]; xevents_array[i].id = i; } Console.WriteLine("Before "); for (i = 0; i < 5; i++) for (j = 0; j < 5; j++) Console.WriteLine(xevents_array[i].id + " " + xevents_array[i].xy_array[j].ytime); xevents_array[0].id = 454; xevents_array[0].xy_array[0].ytime = 454; // notice the hard coded indexes Console.WriteLine("After "); //please explain the result for (i = 0; i < 5; i++) for (j = 0; j < 5; j++) Console.WriteLine(xevents_array[i].id + " " + xevents_array[i].xy_array[j].ytime); while (Console.Read() != 'q'); } } }

Console-Output:

Before 0 0 0 1 0 2 0 3 0 4 1 0 1 1 1 2 1 3 1 4 2 0 2 1 2 2 2 3 2 4 3 0 3 1 3 2 3 3 3 4 4 0 4 1 4 2 4 3 4 4 After 454 454 454 1 454 2 454 3 454 4 1 454 1 1 1 2 1 3 1 4 2 454 2 1 2 2 2 3 2 4 3 454 3 1 3 2 3 3 3 4 4 454 4 1 4 2 4 3 4 4

解决方案

What shock? It does what I would expect.e Your xevents is a struct - which means that it's a valuetype. It contains an array of ytimeframe ojbects, which because it's an array is a reference type, regardless of the type of the objects it is an array of. So when you do this:

for (i = 1; i < 5; i++) //initialize { xevents_array[i] = xevents_array[0]; xevents_array[i].id = i; }

You use a valuetype assignment to copy the individual members of the xecevent_array - which copies the reference to the same array of ytimeframe objects into each and every xevents instance. So when you modify any element of the xy_array you modify the same element in all instances in your xevents_array.

The problem is with this line:

xevents_array[i] = xevents_array[0];

You're copying the value of the xevents structure at position 0 to each element of the array. However, this is a shallow copy. Since the struct contains a reference type (the xy_array array), each copy of the struct will be pointing to the same array instance. When you change a value in the array instance for the first item, all of the other items are updated because they're looking at the same array instance. A simpler demonstration of the issue:

static void Main() { Foo x = new Foo(); x.Bar = new int[1]; x.Bar[0] = 1; Foo y = x; y.Bar[0] = 42; Console.WriteLine(x.Bar[0]); // Output is 42 } public struct Foo { public int[] Bar; }

To resolve the issue, you'll need to clone the array:

// xevents_array[i] = xevents_array[0]; xevents_array[i].xy_array = (ytimeframe[])xevents_array[0].xy_array.Clone();

edit: I just realized I only explained why it doesn't work like you expect in C#, I can't tell why it's different in C++ /edit You replace the references to the individual xy_arrays in xevents_array 1-4 with the reference to the xy_array of xevents_array 0 here:

for (i = 1; i < 5; i++) { xevents_array[i] = xevents_array[0]; // <- here xevents_array[i].id = i; }

So already before the first WriteLine-Loop you're seeing the values from one and the same xy_array and consequentially you change all the zeroes the one zero in the 0-index to 454 here:

xevents_array[0].xy_array[0].ytime = 454;

更多推荐

为什么这在C ++中有效但在C#中无效?

本文发布于:2023-10-29 08:04:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1539160.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:但在   这在

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!