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();
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_2: When I will comment exisiting '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. Then, when 'AddBucketItem' method is called, an 'item' varaible will be set by 'item.SetItem' and then, added to 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].
Questions:
Why each call in Part_2 is changing also all elements which were already added to 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. 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.
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 .
At the same time, in the first code snippet, Item
is a class, which is reference type .
If you use approach described in Part_2
, then you actually operate with one object. So, your ItemList
contains N items, which are all the same object.
In Part_1
, every time you call AddBucketItem
, you create a new object and append it to your list. In Part_2
, everytime you call AddBucketItem
, you modify the single original Item
object.
You may want to read some information on value types and reference types on MSDN:
https://msdn.microsoft.com/en-us/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.
Therefore, your understanding for the AddBucketItem
example is correct. The Item
object is only created once in the BucketItems
constructor. When you call AddBucketItem()
, you are modifying the original instance and adding its reference into the list. 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.