1

I defined a simple class with the following definition. In this sample, I defined a simple class with a single string parameter. Then I instantiated this class and assigned a value to the parameter. I passed that instance to another function without specifying "ref" keyword. It means it should be passed by value instead of reference. But what I don't understand is the reason that the output displays "Second Modification" value as a result instead of "First Modification".

UPDATE 1:

I think my question was confusing. I know how "ref" and "pass by reference" working. I need to know why when I "pass by value", run-time still changes the value of the original instance. By the way, I couldn't find my answer in the proposed links.

UPDATE 2:

I asked this question two years ago. Now I understand all properties of an object (instance of a class) are reference type. It means when I pass an instance of a class to another method, they all behave as a reference to original member of the class.


public class MyClass
{
    public String TestProperty { get; set; }
}

public class TestClass
{
    public TestClass()
    {
        var myClass = new MyClass();
        myClass.TestProperty = "First Modification";
        MyFunction(myClass);
        Console.WriteLine(myClass.TestProperty); // Output: "Second Modification"
    }
    void MyFunction(MyClass myClass)
    {
        myClass.TestProperty = "Second Modification";
    }
}
Saeid
  • 1,573
  • 3
  • 19
  • 37
  • Yes. The *reference* to the instance is passed by value. This is entirely expected behaviour. – J. Steen Dec 01 '14 at 09:54
  • Have a read: http://yoda.arachsys.com/csharp/parameters.html – J. Steen Dec 01 '14 at 09:56
  • Thanks @J.Steen. The link you posted was the asnwer I was looking for. – Saeid Dec 01 '14 at 12:19
  • Reference types are always passed by reference even when passing by value (since the value is the reference) - http://stackoverflow.com/questions/264609/passing-reference-types-by-value-in-c-sharp – RobV Dec 01 '14 at 12:49
  • 1
    Primative types like int, float, bool are passed "by value" but objects (such as your class instance) are passed by reference. At least, the is how most people think of it. Imagine if your class contains 1000 variables. Passing a COPY of the class instance (along with all it's contained values) around with each function call would be both inefficient and undesirable. Your `myClass` variable is a REFERENCE to your instance of your `MyClass` object. When you pass it into a function you are passing that variable (which is a REFERENCE) BY VALUE. Your fn is then using the ref to update props – Chris Walsh Dec 02 '14 at 00:12

2 Answers2

4

You can change the object passed to the method, but you can't change the reference itself without the ref keyword

public class MyClass
{
    public String TestProperty { get; set; }
}

public class TestClass
{
    public TestClass()
    {
        var myClass = new MyClass();
        myClass.TestProperty = "First Modification";

        MyFunction(myClass);
        Console.WriteLine(myClass.TestProperty); // Output: "First Modification"

        MyRefFunction(ref myClass);
        Console.WriteLine(myClass.TestProperty); // Output: "Third Modification"
    }
    void MyFunction(MyClass myClass)
    {
        myClass = new MyClass() { TestProperty = "Second Modification"};
    }

    void MyRefFunction (ref MyClass myClass)
    {
        myClass = new MyClass() { TestProperty = "Third Modification"};
    }
}

If you want to prevent the property being changed, you can make the setter non-public:

public String TestProperty { get; private set; }
Rik
  • 28,507
  • 14
  • 48
  • 67
  • Nice explanation, but doesn't answer my question. Why in "MyFunction" call, if we don't re-instantiate the argument, we can modify the original valu of the property? I need to understant the logic behind. I know how to resolve this. Thanks in advance. – Saeid Dec 01 '14 at 12:15
  • Because the object is mutable. It's supposed to be able to change (because it has a setter), and it's supposed to be changeable by different objects (because it's declared public). You could prevent it from being changed by making the setter non-public: `public String TestProperty { get; private set; }` – Rik Dec 01 '14 at 12:19
0

That is the expected behavior. What ref would allow you to do is create a new object in MyFunction and assign it to the myClass parameter and have the new object available outside the method.

   void MyFunction(ref MyClass myClass)
   {
     myClass = new MyClass(); //this new instance will be accessible outside the current method
   }

Have a look at http://msdn.microsoft.com/en-us/library/14akc2c7.aspx for more details.

Stefan Ch
  • 329
  • 2
  • 7