猿问

代码正在修改错误的变量...为什么?

我有一件奇怪的事情,我正在做的一些代码正在修改副本和原始列表。我已经尽可能地将问题归结为仅在单个文件中显示错误。尽管我在现实世界中的例子要复杂得多.. 但归根结底,这一切都是问题所在。


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;


namespace TestingRandomShit

{

    class Program

    {

        private static string rawInput;

        private static List<string> rawList;

        private static List<string> modifiedList;


        static void Main(string[] args)

        {

            rawInput = "this is a listing of cats";


            rawList = new List<string>();

            rawList.Add("this");

            rawList.Add("is");

            rawList.Add("a");

            rawList.Add("listing");

            rawList.Add("of");

            rawList.Add("cats");


            PrintAll();


            modifiedList = ModIt(rawList);


            Console.WriteLine("\n\n**** Mod List Code has been run **** \n\n");

            PrintAll();

        }


        public static List<string> ModIt(List<string> wordlist)

        {


            List<string> huh = new List<string>();

            huh = wordlist;


            for (int i = 0; i < huh.Count; i++)

            {

                huh[i] = "wtf?";

            }

            return huh;

        }


基本上,我有三个变量......一个字符串和两个列表。原始代码对字符串进行了一些标记,但对于这个演示,我简单地使用 List.Add() 来伪造它以使其易于阅读。


所以我现在有一个字符串和一个列表,每个元素中都有一个单词。


这是我不明白的令人困惑的部分。我知道它与参考有关,但我不知道如何适应它。


有一种方法我称之为 ModIt()...它简单地接受一个列表,然后创建一个名为 huh 的全新列表,将原始列表复制到新列表上,然后将 huh 中的每一行更改为“wtf?”。


现在据我了解..我最终应该得到3个变量...


1) 一个字符串 2) 一个在每个元素中包含不同单词的列表 3) 一个与另一个长度相同且每个元素为“wtf?”的列表


但是,发生的情况是我尝试打印出两个列表,它们都将每个元素都设置为“WTF?”....所以是的.. wtf man?我超级困惑。我的意思是在 ModIt 中,我什至构建了一个全新的字符串,而不是修改正在传递的字符串,但它似乎没有任何影响。


这是输出...


: 原始输入 : 这是猫的列表


: Original List : 这是猫的列表


**** 模组列表代码已运行 ****


: 原始输入 : 这是猫的列表


: 原始列表 : wtf? 什么?什么?什么?什么?什么?


: 修改列表 : wtf? 什么?什么?什么?什么?什么?


弑天下
浏览 124回答 3
3回答

暮色呼如

huh = wordlist;不会将 的项目复制wordlist到新列表中,它会将引用复制到所占用的同一对象wordlist(即huh,wordlist然后指向内存中的同一对象)。如果您想要一份副本,最简单的制作方法是使用 LINQ:List<string>&nbsp;huh&nbsp;=&nbsp;wordlist.ToList();请注意,这将是一个“浅拷贝”。如果您的列表存储引用对象,则旧列表和新列表都将存储对相同对象的引用。有关值与引用类型的更多信息,请参见此处,如果您需要深度副本,请参见此处。由于您所做的只是替换列表索引处的值,我想浅拷贝就可以了。

慕村225694

约翰已经评论了错误代码:&nbsp; &nbsp; &nbsp; &nbsp; List<string> huh = new List<string>();&nbsp; &nbsp; &nbsp; &nbsp; huh = wordlist;在这里您创建一个新列表,然后将其丢弃并将您的参考附加huh到您的旧列表中,因此 huh 和 wordlist 都指的是同一件事..我只是想指出复制列表的非 LINQ 方式:&nbsp; &nbsp; &nbsp; &nbsp; List<string> huh = new List<string>(wordlist);将旧列表传递给新列表的构造函数;list 有一个构造函数,它将对象集合存储在新列表中您现在有两个列表,最初它们都引用相同的字符串,但由于字符串无法更改,如果您开始更改列表中的字符串(而不是仅仅将它们从列表中改组或删除),将创建新的如果是一个有价值的观点;您将有 2 个指向相同对象的列表,因此如果您将来有相同的场景,其中的对象可以更改,并且您在一个列表中更改对象,它也会在另一个列表中更改://imagine the list stores people, the age of the first//person in the list is 27, and we increment itList1[0].PersonAge++;//list2 is a different list but refers to the same people objects//this will print 28Console.Out.WriteLine(list2[0].PersonAge);这就是我们所说的浅拷贝

HUWWW

您的问题来自这样一个事实,即在 C# 中我们有引用类型和值类型。值类型可以通过直接赋值运算符 (&nbsp;=) 进行赋值,但对于引用类型则不同。引用类型本身不存储实际数据,它们在内存中存储数据所在的位置。就像指针一样,如果你来自 C 世界。看看IClonable。另请阅读Jon Skeet 的参数传递,它很好地描述了值和引用类型。
随时随地看视频慕课网APP
我要回答