为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
弑天下 2022-07-10 16:23:13
我有一件奇怪的事情,我正在做的一些代码正在修改副本和原始列表。我已经尽可能地将问题归结为仅在单个文件中显示错误。尽管我在现实世界中的例子要复杂得多.. 但归根结底,这一切都是问题所在。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? 什么?什么?什么?什么?什么?
查看完整描述

3 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

huh = wordlist;不会将 的项目复制wordlist到新列表中,它会将引用复制到所占用的同一对象wordlist(即huhwordlist然后指向内存中的同一对象)。

如果您想要一份副本,最简单的制作方法是使用 LINQ:

List<string> huh = wordlist.ToList();

请注意,这将是一个“浅拷贝”。如果您的列表存储引用对象,则旧列表和新列表都将存储对相同对象的引用。

有关值与引用类型的更多信息,请参见此处如果您需要深度副本,请参见此处。

由于您所做的只是替换列表索引处的值,我想浅拷贝就可以了。


查看完整回答
反对 回复 2022-07-10
?
慕村225694

TA贡献1880条经验 获得超4个赞

约翰已经评论了错误代码:


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

        huh = wordlist;

在这里您创建一个新列表,然后将其丢弃并将您的参考附加huh到您的旧列表中,因此 huh 和 wordlist 都指的是同一件事..


我只是想指出复制列表的非 LINQ 方式:


        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 it

List1[0].PersonAge++;


//list2 is a different list but refers to the same people objects

//this will print 28

Console.Out.WriteLine(list2[0].PersonAge);

这就是我们所说的浅拷贝


查看完整回答
反对 回复 2022-07-10
?
HUWWW

TA贡献1874条经验 获得超12个赞

您的问题来自这样一个事实,即在 C# 中我们有引用类型值类型

值类型可以通过直接赋值运算符 ( =) 进行赋值,但对于引用类型则不同。引用类型本身不存储实际数据,它们在内存中存储数据所在的位置。就像指针一样,如果你来自 C 世界。

看看IClonable。另请阅读Jon Skeet 的参数传递,它很好地描述了值和引用类型。


查看完整回答
反对 回复 2022-07-10
  • 3 回答
  • 0 关注
  • 123 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信