c# by reference or by value - c#

Let's say I have a list of objects and that I'm extracting and modifying an item from the list like this:
List<MyObject> TheListOfObjects = new List<MyObject>();
MyObject TheObject = new MyObject();
TheListOfObjects = //some json deserialization result
TheObject = (from o in TheListOfObject
where o.ID == SomeParameter
select o).SingleOrDefault();
TheObject.SomeProperty = SomeValue;
When I write TheObject.SomeProperty = SomeValue; am I:
modifying the item in the list and in which case I'm done or
modifying a new item and I must replace the original item in the list with the item I just modified.

Depends.
If the list of objects is a list of class instances, then TheObject variable will hold a value that is a reference. This reference will also still exist within the list. Modifications of the object at that reference will be visible in both. Important caveat: Writing over the reference contained in the variable (ie., variable reassignment) would not persist to the list, nor would writing over the reference in the list persist to the variable.
If the list of objects is a list of struct instances, then TheObject simply contains the value, and mutations of that value are not visible inside the list.

That depends on whether the MyObject is a class or a struct.
If it's a class, you're modifying the original object.
If it's a struct, you're modifying a copy.

Items in your list are held by reference, so you're modifying the same object - no need to try to copy it back into the list as it's already there.

You are modifying an item in the list. TheObject is a reference to an unique item in memory.
You can even create multiple lists, all lists will contain references to identical objects in memory.
There is something wrong with your code:
MyObject TheObject = new MyObject();
...
TheObject = (from o in TheListOfObject
where o.ID == SomeParameter
select o).SingleOrDefault();
You are first creating a new instance of the object, the affecting to TheObject a new value.
The = new MyObject(); part of your code is useless. Same for = new List<MyObject>();

You are modifying the item in the list as the call returns a reference to the item in the list, not a copy of it. Also, the object you create with
MyObject TheObject = new MyObject();
is just thrown away, as you change the reference to the newly selected item. You could omit that line and just do:
MyObject theObject = (from o in TheListOfObject
where o.ID == SomeParameter
select o).SingleOrDefault();
I assume that MyObject is a class, and not a struct, because we are mutating it with the operation, and mutable structs are evil

Related

What if I never create new object but keep adding the old object into the List by just updating it's value

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.

How to access a list with an index from a calling function

I am writing a c# console program.
I have a function that returns a list of objects.
e.g the following will return a list of objects.
p.getList();
If I already know the index of the object I want to reference from the list, then how to I access this?
For example I want to do the following which obviously is incorrect:
p.getList()[Index]
This would give me the item in the list at index.
To get around this I have done the following:
List<MyObject> mylist = p.getList();
mylist[Index];
but the above seems inefficient, to have to create a copy just to reference a value.
Any tips on how I can access?
Thanks.
If you don't want the list, but an item and you know the Index then
var item = p.getList()[Index];
syntax is perfectly correct. Please, notice, that List<T> is a reference type, that's why in case of
var list = p.getList(); // reference copy, not the collection cloning
var item = list[Index];
...
var otherItem = list[otherIndex];
the var list = p.getList(); adds a miniscule overhead: it's reference, not the entire collection is being copied.

How to access reference on the list?

Class1 : IClass
{
// ...
}
List<IClass> newList = new List<IClass>();
Class1 obj1 = new Class1();
newList.Add(obj1);
I have list of references, right? Now, the new object comes up. For example obj2 which is an instance of Class1 as well. I would like to assign obj2 to obj1 using reference available on the list(note! I can't access obj1 directly). How could I do it?
I assume you mean that you want obj2 to point to the same value that obj1 originally pointed to. If so then just grab the value out of the list with the indexer
Class1 obj2 = (Class1)newList[0];
Note that I had to insert a cast there. The type of elements in the list is IClass1 but you specified obj2 as Class1.
Another option is to use LINQ to find the exact object you need from the list, if for instance obj1 wasn't the first item:
Class1 obj2
= (Class1)newList.SingleOrDefault(x => x.SomeUniquePropertyOfClass1 == someId);
You might have to compare multiple properties in your object, but I don't know what Class1 looks like.
What he/she means is that you have Object1, Object2(both of the same class) and List of Objects.
List1 points to Object1 and the question is, how to make Object1 point to Object2 using reference from the list.
newList[0] = obj2
would only change the reference on the list, however obj1 would stay immutable.

How do I create a shallow copy of an IEnumerable<T>?

I have an IEnumerable object as:
IEnumerable<string> listSelectedItems;
Which contains three items. Now i created a new object and want to get all items from listSelectedItems, so i wrote this code:
IEnumerable<string> newList = listSelectedItems;
But now when i alter newList, the listSelectedItems also gets altered. How can i achieve altering or creating a new IEnumerable without refernce.
Are you looking for this?
IEnumerable<string> newList = listSelectedItems.ToList();
IEnumerable is an interface, so you can't instantiate it, you need an implementation of it, for example List
IEnumerable<string> newList = new List<string>(listSelectedItems);
In your case setting newList = listSelectedItems means that newList will be just a reference to the listSelectedItems so if the underlying object is changed, newList will reference the changed object.

Modifying item after addition to List does not update list

I have a member variable which is a list of reference types. In a method I create and item, add it to the list. The item is then updated point to another instance but the instance in the list does not get updated (his is in some unit test code). Example looks like
Item localItem = new Item(arg1, arg2);
this.itemList.Add(localItem);
// Do some testing and assertions
localItem = new Item(arg3, arg4); // This does not update the instance of
// localItem in this.ItemList
// Do some more testing and assertions
I can update my tests to fix this but it still caught me by surprise. I supose the List wants to keep the original instance passed through the Add method and cares not if the local variable which was used to pass it in now points to something else. Can anyone maybe confirm this understanding or explain it more clearly?
Ofcourse not. The localItem is a reference to the actual object (not the object itself). The list contains also a reference to this same object. If you assign another item to localItem it now points to another object but the list has still a reference to the old object.
If you want the object in the list to update automatically you must introduce a new object that holds a reference to the item and add this one to the list
public class ItemReference
{
public Item Item { get; set; }
}
Now you can create a local item like this
ItemReference itemRef = new ItemReference();
itemRef.Item = new Item(arg1, arg2);
this.itemReferenceList.Add(itemRef);
itemRef.Item = new Item(arg3, arg4);
Because the list now has a reference to the same (unchanged) itemRef it "sees" the new item as well.
The list has to be declared as
List<ItemReference> itemReferenceList;
When you add localItem to the list you add a reference to the object instance (assuming Item is a reference type aka a class) - when you subsequently create a new Item instance the result is a new reference (similar to a pointer) - if you want to update the list you have to remove the old item and add the new item - these are two totally different instances. Alternatively you can modify any properties on localItem and these will be reflected when you access the item through the list.

Categories

Resources