[英]C# Class as other class variable, scope of live
我创建了一小段代码以测试项目的一部分。 它正在工作,但是我有一些疑问...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace testtodel
{
class Program
{
private class BucketItems
{
private List<Item> ItemList;
private Item item;
public BucketItems()
{
//item = new Item();
ItemList = new List<Item>();
}
public void AddBucketItem(int _Start, int _End)
{
item = new Item();
item.SetItem(_Start, _End);
ItemList.Add(item);
}
public void PrintItemList()
{
for (int i = 0; i < ItemList.Count(); i++)
{
Console.WriteLine("Item: " + i.ToString() + " S: " + ItemList[i].Start.ToString() + " E: " + ItemList[i].End.ToString() + " D: " + ItemList[i].Range.ToString());
}
}
}
private class Item
{
public int Range { get; set; }
public int Start { get; set; }
public int End { get; set; }
public void SetItem(int _Start, int _End)
{
Start = _Start;
End = _End;
Range = _End - _Start;
}
}
static void Main(string[] args)
{
BucketItems bucketItems = new BucketItems();
bucketItems.AddBucketItem(0, 100);
bucketItems.AddBucketItem(200, 300);
bucketItems.AddBucketItem(700, 1000);
bucketItems.PrintItemList();
Console.ReadLine();
}
}
}
我不完全了解的东西与线有关
item = new Item();
正如您在代码中看到的那样,有两行是这样的,其中一行已注释,而另一行未注释。
Part_1:按原样执行代码时,每次调用“ AddBucketItem”方法时,它将创建一个“ Item”类的新实例,然后“ Item.SetItem”将设置“开始”,“结束”,“范围” '在'item'变量中,它将被添加到'ItemList'中。
第2部分:当我要评论现有的“ item = new Item();”时 行和取消注释其他一个,那么我将期待以下内容。 创建BucketItem类的新实例时,它还将创建“ Item”的新实例,这是在“ BucketItem”构造函数中定义的。 然后,当调用“ AddBucketItem”方法时,“ item”变量将由“ item.SetItem”设置,然后添加到ItemList。 第一次迭代就可以。 但是,如果我再次使用新的“开始”和“结束”参数调用“ AddBucketItem”方法,这也会更改已添加的ItemList [0]。
问题:
为什么在Part_2中的每个调用都会更改已经添加到ItemList中的所有元素? 唯一的解释是列表中的所有元素都存储着对“ item”变量的引用,并且当通过更改(开始,结束,持续时间)更改此变量时,它还将更改所有ItemList。 但是我不知道这是正确的解释,还是我不知道为什么会这样。 但是,我假设答案是不同的,因为即使我做与“ Part2”中完全相同的操作,以下示例也将按预期填充列表。.我有变量,我正在更改变量的值,我要添加此变量列出。
int new_val; List<int> _lst = new List<int>(); for (int i = 0; i < 10; i++) { new_val = i; _lst.Add(new_val); } for (int i = 0; i < _lst.Count(); i++) { Console.WriteLine("ListIdx: " + i.ToString() + " Value: " + _lst[i].ToString()); }
有人可以请问我的问题吗?
在您的示例中, new_val
是int
,它是value类型 。
同时,在第一个代码段中, Item
是一个类,它是引用类型 。
如果使用Part_2
描述的Part_2
,则实际上是对一个对象进行操作。 因此,您的ItemList
包含N个项目,它们都是相同的对象。
在Part_1
,每次调用AddBucketItem
,都会创建一个新对象并将其附加到列表中。 在Part_2
,每次调用AddBucketItem
,都将修改单个原始Item
对象。
您可能需要阅读有关MSDN上的值类型和引用类型的一些信息:
https://msdn.microsoft.com/zh-CN/library/4d43ts61(v=vs.90).aspx
您需要了解,在C#中,对象是通过引用传递的,而原始类型是通过值传递的。
因此,您对AddBucketItem
示例的理解是正确的。 Item
对象在BucketItems
构造函数中仅创建一次。 调用AddBucketItem()
,您正在修改原始实例并将其引用添加到列表中。 因此,最后,您将获得一个列表,其中包含所有指向同一对象实例的单个项目。
对于您提供的第二个示例,它的行为有所不同,因为对于int
类型(它是原始数据类型),传递给Add()
函数的值是整数的副本,而不是引用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.