Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Why is this object not modified after the function is executed?

Tags:

c#

I always thought that objects where always passed as reference in C# and that if a function modifies it then the parent method should have a modified version of that object. However, reading this code that was left by an old developer that was causing a bug makes me think that this is not always the case. The code is the following:

Item item = new Item();
PopulateItem(sodItem, id, item);

The function code is the following:

private void PopulateItem(eSodTypes.Item sodItem, int id, Item item)
        {

                if (sodItem != null)
                {
                    item = (Item)sodItem;
                    item.Delivery = (Delivery)sodItem.Delivery;
                    if (sodItem.Delivery != null)
                    {
                        item.Delivery.DeliveryContact = (CustomerContact)sodItem.Delivery.DeliveryContact;
                        item.Delivery.DeliveryAddress = (Address)sodItem.Delivery.DeliveryAddress;
                        item.Delivery.ShippingInstructions = (ShippingInstructions)sodItem.Delivery.ShippingInstructions;
                    }
                    item.Installation = (Installation)sodItem.Installation;
                    item.Training = (Training)sodItem.Training;
                    item.Service = (Service)sodItem.Service;
                    item.Service.Address = (Address)sodItem.Service.Address;
                    if (sodItem.Service.Address != null)
                        item.Service.Address.Contact = (CustomerContact)sodItem.Service.Address.Contact;
                    item.Service.Customer = (Customer)sodItem.Service.Customer;
                    if (sodItem.ItemLines != null)
                        item.ItemLines = sodItem.ItemLines.Items.ToList().ConvertAll(new Converter<eSodTypes.ItemLine, ItemLine>(ItemLine.ItemLineTypeToItemLineTypeModel));
                }
        }

If I use "ref" with the item it works, but I thought this was only for value types like "int" or "double".

like image 943
paddingtonMike Avatar asked Sep 19 '11 15:09

paddingtonMike


3 Answers

You will have to use the ref keyword to get this to work. The difference is subtle ... when you pass an object the pointer is passed by value .. ie it is copied. So now you have two pointer pointing to the same thing. When you then assign a new object to the parameter pointer you do not affect the original pointer .. its still points to the original.

When you use ref the pointer is literally passed so if you reassign it then the original pointer is also reassigned.

More info here ... http://msdn.microsoft.com/en-us/library/14akc2c7.aspx

To make yours work you will either ...

a) need to use the ref keyword or b) do this item = (Item)sodItem; before passing it to the method

like image 55
iDevForFun Avatar answered Sep 30 '22 14:09

iDevForFun


I have a piece of paper with an address on it: 123 Sesame Street. I hand you a photocopy of that piece of paper.

You proceed to 123 Sesame Street and find a blue house. You paint the house green.

You then cross out 123 Sesame Street on your photocopy and replace it with 1600 Pennsylvania Avenue.

My piece of paper with the address on it does not change. I go to 123 Sesame Street, and sure enough, the house is now green.

You see? The house was "passed by reference" when I made my photocopy. The piece of paper is not a house; it is a reference to a house. A copy of that reference is still a reference to the house. Changing one reference does not change any other reference; changing the colour of the thing referred to changes that colour for all references.

Suppose by contrast I share my piece of paper with you instead of making a copy. Now if you scratch out 123 Sesame Street and replace it with 1600 Pennsylvania Avenue, I see the change because we are sharing the same reference. You share a variable with a method by using the "ref" keyword.

Make sense?

like image 44
Eric Lippert Avatar answered Sep 30 '22 14:09

Eric Lippert


I'm assuming you mean that you expect that 'item' will be modified upon return from the method. The problem is here:

item = (Item)sodItem;

You're modifying the variable item to point to the parameter sodItem, so it's no longer pointing to the same item that was passed in. The original reference 'item' was never modified. When you change the item parameter to 'ref', this does cause the original reference of the variable passed as a parameter to change.

Note that this current code is actually modifying the original sodItem (copying its own values back to itself), which might not be your intention.

like image 44
Dan Bryant Avatar answered Sep 30 '22 16:09

Dan Bryant