【问题标题】:C# Class as other class variable, scope of liveC# 类作为其他类变量,活动范围
【发布时间】:2017-01-02 21:20:05
【问题描述】:

我创建了一小段代码来测试我的项目的一部分。它正在工作,但是我有一些问题......

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

正如您在代码中看到的那样,有 2 行这样的行,1 行注释,1 行未注释。

  • 第 1 部分: 当代码按现在这样执行时,每次调用 'AddBucketItem' 方法时,它都会创建一个新的 'Item' 类实例,然后 'Item.SetItem' 将设置 'Start'、'End'、'Range' 在'item' 变量,这将被添加到 'ItemList' 中。

  • 第 2 部分: 当我评论现有的 'item = new Item();'行并取消注释另一个然后我会期待以下。当创建 BucketItem 类的新实例时,它还将创建一个新的 'Item' 实例,因为它是在 'BucketItem' 构造函数中定义的。然后,当调用'AddBucketItem' 方法时,'item' 变量将由'item.SetItem' 设置,然后添加到ItemList。 这对于第一次迭代是可以的。但是,如果我再次调用 'AddBucketItem' 方法,使用新的 'Start' 和 'End' 参数,这也会改变已添加的 ItemList[0]。

  • 问题:

  • 为什么 Part_2 中的每个调用都会更改已添加到 ItemList 的所有元素?唯一的解释是列表中的所有元素都存储对“项目”变量的引用,并且当通过更改(开始、结束、持续时间)更改此变量时,它也会更改所有 ItemList。但我不知道这是否是正确的解释,如果是,我不知道它为什么会这样。悬停我假设答案是不同的,因为即使我在做与“第 2 部分”完全相同的事情,以下示例也会按预期填充列表。我有变量,我正在更改变量的值,我正在添加这个变量列出来。

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

    有人可以详细说明我的问题吗?

【问题讨论】:

    标签: c# list class scope


    【解决方案1】:

    在您的示例中,new_valint,这是 值类型
    同时,在第一个代码sn-p中,Item是一个类,是引用类型

    如果您使用Part_2 中描述的方法,那么您实际上是在使用 one 对象进行操作。因此,您的 ItemList 包含 N 个项目,它们都是同一个对象。

    Part_1 中,每次调用AddBucketItem 时,都会创建一个新对象并将其附加到列表中。 在Part_2 中,每次调用AddBucketItem 时,都会修改单个原始Item 对象。

    您可能想阅读 MSDN 上有关值类型和引用类型的一些信息:
    https://msdn.microsoft.com/en-us/library/4d43ts61(v=vs.90).aspx

    【讨论】:

    • 我通读了提到的文章,发现了一些有趣的东西。提到:“当使用基本的内置数据类型或用户定义的结构之一声明变量时,它是值类型。字符串数据类型是一个例外,它是引用类型。”。但是,当我将最后一个示例从 int 更改为 string 时,它仍然可以正常工作。那么字符串是不是引用类型?
    【解决方案2】:

    您需要了解,在 C# 中,对象是通过引用传递的,而原始类型是通过值传递的。

    因此,您对AddBucketItem 示例的理解是正确的。 Item 对象仅在 BucketItems 构造函数中创建一次。当您调用AddBucketItem() 时,您正在修改原始实例并将其引用添加到列表中。所以最后,你有一个列表,其中的单个项目都指向同一个对象实例。

    对于您提供的第二个示例,它的行为有所不同,因为对于基本数据类型 int 类型,传递给 Add() 函数的值是整数的副本,而不是引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-18
      • 2012-02-24
      • 1970-01-01
      • 1970-01-01
      • 2014-03-21
      • 2013-01-16
      • 2012-05-10
      • 2016-10-25
      相关资源
      最近更新 更多