1

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:

  1. modifying the item in the list and in which case I'm done or
  2. modifying a new item and I must replace the original item in the list with the item I just modified.
Didier Ghys
  • 30,396
  • 9
  • 75
  • 81
frenchie
  • 51,731
  • 109
  • 304
  • 510
  • 5
    You've already written the code; try it and see what happens! – Eric Lippert Feb 16 '12 at 15:05
  • 1
    I don't understand why you're creating *new* objects and then just throwing them away by assigning new instances to the variables? – Chris Dunaway Feb 16 '12 at 15:14
  • @EricLippert: sometimes things work by accident and then stop working later, I just wanted to clarify that what I've got is really what I wanted. You read about byval vs byref in books but it's in practice that you really learn. – frenchie Feb 16 '12 at 15:33
  • @ChrisDunaway: how should this code be written? – frenchie Feb 16 '12 at 15:34
  • @frenchie re Chris's comment: see ken2k's answer for an explanation. – phoog Feb 16 '12 at 18:14
  • I was referring to the use of new in the code you supplied. Your code creates a new object and then throws it away! Instead you would just use something like: List TheListOfObjects = //some json deserialization result; The call to new is redundant. – Chris Dunaway Feb 16 '12 at 22:20

5 Answers5

6

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.

Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
5

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.

GSerg
  • 76,472
  • 17
  • 159
  • 346
1

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

Community
  • 1
  • 1
SWeko
  • 30,434
  • 10
  • 71
  • 106
1

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.

Yuck
  • 49,664
  • 13
  • 105
  • 135
1

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

ken2k
  • 48,145
  • 10
  • 116
  • 176
  • I guess it feels more readable to me to have all my variables declared at the beginning of a function; is there a performance impact in the way I'm doing it? Alternative could be MyObject TheObject = null; Better like this? – frenchie Feb 16 '12 at 18:46
  • @frenchie It is generally not recommended in C# to declare variables at the beginning of the method (was true in C, but not in C# anymore). It is generally preferred to declare variables **as close as possible to their usage**. That said, if you really want to declare variables at the beginning of your function, then `MyObject TheObject = null;` is way much better than `MyObject TheObject = new MyObject();` but `MyObject TheObject;` would be enough. – ken2k Feb 16 '12 at 19:59