views:

113

answers:

4

Hi all,

I am passing one parameter/object to the function "RefValTest(object oIn)" by the value but after function call is over object passed by the value is changed, that shoud not happened, right ?

    class MilanTest
    { 
        public int SomeValue { get; set; }
    }

    class PR
    {

      public static object RefValTest(object oIn)
      { 

        PropertyInfo tProperty = oIn.GetType().GetProperty("SomeValue");
        tProperty.SetValue(oIn, 5, null);

        return null;
       }

     }

somewhere in the main:

        MilanTest x = new MilanTest ();
        //here is by compiler default x.Somevalue == 0

        PR.RefValTest(x);
        //here is by compiler default x.Somevalue == 5

How it is possible that after call of "PR.RefValTest(x)" value of object x.SomeValue is changed ?

Br, Milan.

A: 

You cannot change the reference oIn but you can change its properties.

So inside your method, if you say

oIn = "SomeString";

on the outside you wouldn't see this.

Ronald Wildenberg
+2  A: 

Very simply: what's being passed into the method is a reference to the object. You're then changing the data within that object. So when you look at the object again afterwards, you can see the change.

You don't need to use reflection to see this working - here's a simpler version of your code:

class MilanTest
{ 
    public int SomeValue { get; set; }
}

class Test
{
    static void RefValTest(MilanTest x)
    { 
        x.SomeValue = 5;
    }

    static void Main()
    {
        MilanTest t = new MilanTest();
        RefValTest(t);
        Console.WriteLine(t.SomeValue); // Prints 5
    }
}

See my article on parameter passing for more details.

Jon Skeet
Additionally, when passing the parameter as "ref object oIn", you'd also be able to change the reference itself. That means "oIn = someOtherObject" would (in your sample) make "x" another object.
Thorsten Dittmar
A: 

Wrong. This should happen, whether you set the value directly or take the detour over reflection. This is what pass-by-reference means: you are interacting with the same object instance, not a copy.

Pontus Gagge
Except that this *isn't* pass-by-reference, it's pass reference by value.
Jon Skeet
Nitpick accepted...
Pontus Gagge
@Pontus: You may call it a "nitpick", but it's a source of significant confusion, particularly as C# *does* have proper pass-by-reference semantics with `ref`.
Jon Skeet
@Jon: I don't disagree. In the present case, though, the confusion seemed to me to be on a more fundamental level.
Pontus Gagge
+2  A: 

The problem is that you're confusing what you're passing, and passing an object "by value" never quite works.

When you pass a reference type (anything derived from System.Object), what you're passing is a reference to that object - not the object itself. Essentially you're passing the memory address that the object's data is stored at. Whether you pass this by reference or by value, what happens inside the method is that the address is followed to your original object. Whether you pass a "pointer to the address" or "a copy of the address", the address itself doesn't change.

So, regardless of how you pass that type, you're going to find that the original object is what you're modifying. Your alternative, if you really need this functionality, is to create a clone of the object and pass in the clone instead (or make your method create the clone itself). That way the clone is modified instead of your original object.

Dan Puzey
Hi Dan, Thorsten, Jon,you all answerd my question but Dan Puzey explained it in more details! Thanks to all !
Milan
@Milan: I let the linked article give more detail in this case - I've spent *far* too long writing about this over the years ;) (I'm in no way suggesting that you change the accepted answer, but please read over that article if you have any lingering doubts.)
Jon Skeet