I need to store two variables and then check if they have not changed.
List<CatalogInfo> list_catalogs = new List<CatalogInfo>();
List<FileInfo> list_files = new List<FileInfo>();
List<CatalogInfo> list_catalogs_for_check_changed = new List<CatalogInfo>();
List<FileInfo> list_files_check_changed = new List<FileInfo>();
When I do:
list_catalogs_for_check_changed = list_catalogs;
list_files_check_changed = list_files;
But When I add to list_catalogs or list_files Items I see in debager that Items add to list_catalogs_for_check_changed or list_files_check_changed. Why??? I don't add Items to with variables.
list_catalogs.Add(new CatalogInfo() { Action = "Create", Path = folderBrowserDialog1.SelectedPath });
When you do this:
list_catalogs_for_check_changed = list_catalogs;
You are not making a copy of the list, you are assigning a new reference to the same list. If you want to create a new list with the same items, do this:
list_catalogs_for_check_changed = new List<CatalogInfo>(list_catalogs);
This assigns a new List<CatalogInfo> and passes the list from which to copy the elements, resulting in two independent lists with the same items.
I don't add Items to with variables.
Indeed, you don't. You are adding items to the lists. If you do (from the question):
list_catalogs_for_check_changed = list_catalogs;
list_files_check_changed = list_files;
Then both list_catalogs_for_check_changed and list_catalogs hold a reference to the same list of CatalogInfo. Likewise, list_files and list_files_check_changed hold a reference to the same list of FileInfos. It therefore follows that if you add an item to that list, it will be visible via either variable.
The variable is not the list: the list is somewhere on the managed heap. The variable is just the reference to the list. Assigning one list variable to another copies the reference. It does not make a copy of the list.
When you do
list_catalogs_for_check_changed = list_catalogs;
You are handing over a reference to list_catalogs. You want to copy it.
This is an article describing value types vs reference
Related
I have List<string> I am passing from model to control and back again. My initial problem was that when I use List.remove() to remove an item from the list<> it is somehow coming back when passing it back to the View.
I decided to create a new list<>, put the model.List<> values in it, clear the Model.List<>, and then put the values from the tmp List<> back in the Model.List<>.
However, when I clear the Model.List<> the tmp List<> values are being cleared as well.
if (!string.IsNullOrEmpty(model.removeDate))
{
model.multipleSingleDay_Date.Remove(model.removeDate);
List<string> tmpV = new List<string>();
tmpV = model.multipleSingleDay_Date;
model.multipleSingleDay_Date.Clear();
model.multipleSingleDay_Date = tmpV;
}
You are using a reference to the original list.
To make a new list, use a new List<string>(); and iterate through your original list to fill the new one. This can be done in several ways.
tmpV = model.multipleSingleDay_Date;
All the above line does is say "the reference the variable model.multipleSingleDay_Date has should be used in the tmpV variable".
Loop through the original list and add each value to the new list. Or copy the list, see comments below.
In a for loop, instead of declaring a new object and add it to my List, I just update the value of the old object and every time keep adding this old object to my List, why after a few loops all List elements become the same
foreach (vg_ts_VesselCashflow_CashFlow_Entity item in cashflow)
{
var result = new VslMonthlyCashflow_Record();
result.CapitalCost = item.CapitalCost;
result.CharterRevenue = item.CharterRevenue;
result.Date = item.Period;
result.DryDock = item.DryDock;
resultList.Add(result);
}
if (resultList != null)
return resultList;
//Compared with this:
var result = new VslMonthlyCashflow_Record();
foreach (vg_ts_VesselCashflow_CashFlow_Entity item in cashflow)
{
result.CapitalCost = item.CapitalCost;
result.CharterRevenue = item.CharterRevenue;
result.Date = item.Period;
result.DryDock = item.DryDock;
resultList.Add(result);
}
I expect my resultList to be updated but if I keep using the old object, when it loops 123 times, all elements in the List will be the same.
List#Add doesn't copy the object or anything like that, it just keeps a reference to the object you passed to it. In the second snippet, you keep adding the same object to the list multiple times. Each modification you perform on the object is visible through all the references pointing to it, including the local result variable and all the elements of the list.
Hi I have a list of objects(list1) and I'd like to make a copy of this list but I want that the objects in the second list(list2) to not be linked to the one in first list.
this is what I do
list<Obj> list1 = new list<Obj>{};
// I fill the list1 with objects Obj
// now I want to make a deep copy this is what I do
list<Obj> list2 = new list<Obj>(list1);
// but when I edit an object in list 1 I also edit the object in list2
I'd like to be able to edit the objects in list1 without edititng the object in list2,how can I get that???
thanks for your answers
You should implement the ICloneable interface in your Obj class. After that, you can call this code to create your second list:
list<Obj> list2 = new list<Obj>(list1.Select(x => x?.Clone()));
It will clone every item in the list. (With null-check)
You could add a copy constructor to your Obj.
Then loop through list1 create a new instance of your objects using the copy constructor and add it to list2.
Example:
Copy constructor:
public Obj(Obj copyFrom)
{
this.field1 = copyFrom.field1;
.
.
}
With the following LINQ query you have a one liner to use the above contructor:
list2.AddRange(list1.Select(s => new Obj(s)));
EDIT:
To whoever marked the question as duplicate. That question is for how to create a deep copy. My question was how to make sure a the copy constructor is called when copying a list of class elements.
I'm trying to make a deep copy of a List that contain custom class elements. If I have a List of strings I can just use
List<string> secondList = new List<string>(firstList);
and then freely modify the elements in the second list without effeting the ones in the firwst list. But when I try to do the same with a custom class type both lists get changed. To try and solve it I made a small test program that just has this class.
class TestClass
{
public string name;
public TestClass(string n)
{
name = n;
}
public TestClass(TestClass original)
{
name = original.name;
}
}
And all my program does is this
TestClass t = new TestClass("Name1");
List<TestClass> list1 = new List<TestClass>();
list1.Add(t);
List<TestClass> list2 = new List<TestClass>(list1);
list2[0].name = "Name2";
That last line of code changes the name of the first element in both lists, which I do no want.
The issue here is that your objects are reference types, and the lists hold references to those objects.
This means that even though your second list has a COPY of the references from the first list, the references are still pointing to the original objects.
In order to solve this, you must clone not the references in the lists but instead the actual objects that you have stored in the lists.
You have already defined a copy constructor for your class, so you can use that to make a deep copy of the list as follows:
var list2 = list1.Select(item => new TestClass(item)).ToList();
You create a reference with this line of Code:
List<TestClass> list2 = new List<TestClass>(list1);
But you won't like to use Call-by-Reference. You Need Call-by-Value
in this Approach.
so the working code in lambda-expression is the following one:
TestClass t = new TestClass("Name1");
List<TestClass> list1 = new List<TestClass>();
list1.Add(t);
List<TestClass> list2 = new List<TestClass>();
list2 = list1.Select(item => new TestClass(item)).ToList();
list2[0].name = "Name2";
Have fun with it...
I have a List that receives ids. It is instantiated outside the foreach statement.
List<int> indices = new List<int>();
foreach (var m in docsRelacionadosModel)
{
//.. do stuff
modelTemp.indices = indices;
//..here I do more stuff and some time it goes to the next iteration and I need to keep the value in indices to get more values.
//although in a condition
if(isOk) {
//I save the value of this list to a model
model.indices = modelTemp.indices;
//And I need to clear the list to get new values
indices.Clear(); <--- This will clear the values saved in model.indices
}
}
As it has values passed by reference, how can I keep the values in model.indices?
You need to make a copy of the list and save that copy to model.indecies. While there are a number of ways of copying the list the LINQ ToList extension method is probably the most convenient:
model.indices = modelTemp.indices.ToList();
Another option is to just use the List constructor:
model.indices = new List<int>(modelTemp.indices);
Just create a copy of the list:
model.indices = new List<int>(modelTemp.indices);
As per this S/O question, the easiest way may be to call ToList on your list:
model.indices = modelTemp.indices.ToList();
You could also instantiate as a new list, passing your list as a constructor parameter.