简体   繁体   English

C#类作为其他类变量,生存范围

[英]C# Class as other class variable, scope of live

I created a small piece of code in order to test part of my project. 我创建了一小段代码以测试项目的一部分。 It is working however I have some questions... 它正在工作,但是我有一些疑问...

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();
        }
    }
}

The thing which I do not fully understand is related to line 我不完全了解的东西与线有关

item = new Item(); item = new Item();

As you can see in code there are 2 lines like that, one commented and one uncommented. 正如您在代码中看到的那样,有两行是这样的,其中一行已注释,而另一行未注释。

  • Part_1: When code is executed as it is now, it will create a new instance of 'Item' class each time when 'AddBucketItem' method is called, then 'Item.SetItem' will set 'Start', 'End', 'Range' within 'item' variable and this will be added to 'ItemList'. Part_1:按原样执行代码时,每次调用“ AddBucketItem”方法时,它将创建一个“ Item”类的新实例,然后“ Item.SetItem”将设置“开始”,“结束”,“范围” '在'item'变量中,它将被添加到'ItemList'中。

  • Part_2: When I will comment exisiting 'item = new Item();' 第2部分:当我要评论现有的“ item = new Item();”时 line and uncomment other one then I will expect the following. 行和取消注释其他一个,那么我将期待以下内容。 When new instance of BucketItem class is created it will also create a new instance of 'Item' as this is defined in the 'BucketItem' constructor. 创建BucketItem类的新实例时,它还将创建“ Item”的新实例,这是在“ BucketItem”构造函数中定义的。 Then, when 'AddBucketItem' method is called, an 'item' varaible will be set by 'item.SetItem' and then, added to ItemList. 然后,当调用“ AddBucketItem”方法时,“ item”变量将由“ item.SetItem”设置,然后添加到ItemList。 This is ok for the first iteration. 第一次迭代就可以。 However if I will call 'AddBucketItem' method again, with new 'Start' and 'End' parameters, this will also change already added ItemList[0]. 但是,如果我再次使用新的“开始”和“结束”参数调用“ AddBucketItem”方法,这也会更改已添加的ItemList [0]。

  • Questions: 问题:

  • Why each call in Part_2 is changing also all elements which were already added to ItemList? 为什么在Part_2中的每个调用都会更改已经添加到ItemList中的所有元素? The only explanation is that all elements from list are storing a reference to 'item' variable and when this variable is changed by changing (Start, End, Duriation) it wil also change all ItemList. 唯一的解释是列表中的所有元素都存储着对“ item”变量的引用,并且当通过更改(开始,结束,持续时间)更改此变量时,它还将更改所有ItemList。 But I don't know if this is correct explanation and if it is I don't know why it is behaving like this. 但是我不知道这是正确的解释,还是我不知道为什么会这样。 Hovever I am assuming that answer is different becasue the following example will fill the list as expected even when I am doing exactly the same thing as in 'Part2'.. I have variable, I am changing value of variable, I am adding this variable to list. 但是,我假设答案是不同的,因为即使我做与“ 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()); } 

    Can someone please put some more light on my issue? 有人可以请问我的问题吗?

In your example, new_val is int which is value type . 在您的示例中, new_valint ,它是value类型
At the same time, in the first code snippet, Item is a class, which is reference type . 同时,在第一个代码段中, Item是一个类,它是引用类型

If you use approach described in Part_2 , then you actually operate with one object. 如果使用Part_2描述的Part_2 ,则实际上是对一个对象进行操作。 So, your ItemList contains N items, which are all the same object. 因此,您的ItemList包含N个项目,它们都是相同的对象。

In Part_1 , every time you call AddBucketItem , you create a new object and append it to your list. Part_1 ,每次调用AddBucketItem ,都会创建一个新对象并将其附加到列表中。 In Part_2 , everytime you call AddBucketItem , you modify the single original Item object. Part_2 ,每次调用AddBucketItem ,都将修改单个原始Item对象。

You may want to read some information on value types and reference types on MSDN: 您可能需要阅读有关MSDN上的值类型和引用类型的一些信息:
https://msdn.microsoft.com/en-us/library/4d43ts61(v=vs.90).aspx https://msdn.microsoft.com/zh-CN/library/4d43ts61(v=vs.90).aspx

You need to understand that in C#, objects are passed by reference and primitive types are passed by value. 您需要了解,在C#中,对象是通过引用传递的,而原始类型是通过值传递的。

Therefore, your understanding for the AddBucketItem example is correct. 因此,您对AddBucketItem示例的理解是正确的。 The Item object is only created once in the BucketItems constructor. Item对象在BucketItems构造函数中仅创建一次。 When you call AddBucketItem() , you are modifying the original instance and adding its reference into the list. 调用AddBucketItem() ,您正在修改原始实例并将其引用添加到列表中。 So in the end, you have a list with individual item all pointing to the same object instance. 因此,最后,您将获得一个列表,其中包含所有指向同一对象实例的单个项目。

For the 2nd example you provide, it behaves differently because for int type, which is a primitive data type, the value passed into the Add() function is a copy of the integer, not a reference. 对于您提供的第二个示例,它的行为有所不同,因为对于int类型(它是原始数据类型),传递给Add()函数的值是整数的副本,而不是引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM