Tony The Lion
Tony The Lion

Reputation: 63310

C# objects by Ref

If one passes an object to a method using the 'Ref' keyword then what is the difference with passing it without the ref keyword?

Because both yield the same result, that the object has been altered when passing control back to the calling object.

Such as this:

 class Student
{
    public string Name
    {
        get;
        set;
    }

    public int Age
    {
        get;
        set;
    }
}
class Program
{
    static Student student = new Student();
    static void Main( string[] args )
    {

        student.Age = 30;
        student.Name = "StudentA";

        Console.WriteLine("Original Student: {0}, Age: {1}", student.Name, student.Age);

        SetStudent(ref student);

        Console.WriteLine("Student by Ref {0}, Age{1}", student.Name, student.Age);

        AnotherStudent(student);

        Console.WriteLine("Just Another Student {0}, Age {1}", student.Name, student.Age);
        Console.ReadLine();
    }

    public static void SetStudent( ref Student student )
    {
        student.Age = 16;
        student.Name = "StudentY";
    }

    public static void AnotherStudent( Student studenta )
    {
        if (studenta.Equals(student))
        {
            Console.WriteLine("The same object in memory");
        }
        studenta.Age = 12;
        studenta.Name = "StudentX";
    }
}

When the student object is passed to AnotherStudent() it gets altered, event thought it is not passed by 'Ref'.

Can someone explain what is happening here?

EDIT

So what is the difference to passing a pointer to an object in C++ in a function?

Tony

Upvotes: 0

Views: 2341

Answers (8)

JohnIdol
JohnIdol

Reputation: 50137

I am limiting the discussion to reference types (everything that is a class, meaning I am not talking about structs or built-in value types). For a full and more detailed discussion you can see this link here.

If you pass reference types without the ref keyword you are passing the reference by value, meaning that a copy of your reference will be made. At this point you can modify the object the ref is pointing to, BUT if you swap in another object (assigning to the ref object you passed in some other object you create) when the function returns the original object that lives outside the function that you passed in is still pointing to the same old reference.

If you pass reference types using the ref keyword instead you can swap in the object you passed in with something else because the reference is not merely being copied - the variable itself is being passed in flesh and bones to the function to do whatever, and you can even make it point to some other address in memory (instantiating another object and assigning it to your ref parameter).

As you point out, in both cases you will be able to modify your object. Basically passing by reference in C# corresponds to passing a simple pointer in C++, while passing without the ref keyword corresponds to passing a constant pointer in C++ (you can make changes but can't make it point to smt else).

Upvotes: 2

Guffa
Guffa

Reputation: 700850

Passing a variable by reference and passing a reference type is two different things. You can combine them by passing a reference type varaible by reference.

Passing a variable by reference simply means that the method can change the variable. The method gets access to the variable itself, not just a copy of the value. A variable doesn't have to be a reference type to be passed by reference. The few cases where passing by reference is used is actually mostly with value types.

When passing a reference type by reference, that means that the method gets access to the reference variable, not just a copy of the reference to the object. The method not only have access to the object, but it can also replace the reference in the variable with a reference to a different object.

Passing by reference is rarely needed, and certainly not something that you need to do just because you are passing a reference type as a parameter.

Upvotes: 1

Esben Skov Pedersen
Esben Skov Pedersen

Reputation: 4517

These examples illustrates the difference

methodA(ref object a)
{
      a = new object();
}

 methodB(object a)
{
     a = new object();
}

object c = new object();
methodA(ref c); //now c points to an entire new object
methodB(c); // does not change the value of c

Upvotes: 0

Phil Ross
Phil Ross

Reputation: 26120

Try changing your two Student methods to:

public static void SetStudent( ref Student student )
{
    student = new Student();
    student.Age = 16;
    student.Name = "StudentY";
}

public static void AnotherStudent( Student studenta )
{
    studenta = new Student();
    studenta.Age = 12;
    studenta.Name = "StudentX";
}

The call to SetStudent will now change your static student variable to reference a new instance because it is passed as a ref. The call to AnotherStudent won't change the reference.

Upvotes: 2

Bob
Bob

Reputation: 99824

Try reassigning the student object rather than setting properties of it.

public static void SetStudent( ref Student student )
{
    student = new Student();
    student.Age = 16;
    student.Name = "StudentY";
}

public static void AnotherStudent( Student studenta )
{
    studenta = new Student();
    studenta.Age = 12;
    studenta.Name = "StudentX";
}

Don't think of ref as "passing by reference" because all reference types are passed by reference. Think of it as "reference to this object can be reassigned"

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1503869

Passing by reference allows the method to change the value of the argument passed to the method - so for a reference type, that allows it to change a variable's value to refer to a different object. Here's an example:

using System;
using System.Text;

class Test    
{    
    static void PassByValue(StringBuilder x)
    {
        x.Append(" - Modified object in method");
        x = new StringBuilder("New StringBuilder object");
    }

    static void PassByReference(ref StringBuilder x)
    {
        x.Append(" - Modified object in method");
        x = new StringBuilder("New StringBuilder object");
    }

    static void Main()
    {
        StringBuilder builder = new StringBuilder("Original");
        PassByValue(builder);
        Console.WriteLine(builder);

        builder = new StringBuilder("Original");
        PassByReference(ref builder);
        Console.WriteLine(builder);
    }
}

In both cases, the original StringBuilder has its contents modified, and then the parameter is assigned a new value. In the "pass by value" case, this doesn't change the value of the builder variable in Main. In the "pass by reference" case, the value of builder refers to the new StringBuilder, so the results are:

Original - Modified object in method
New StringBuilder object

In your case, you're not seeing any difference with or without ref because you're not changing the value of the parameter itself - only the data in the object it refers to.

For more information, see my article on parameter passing.

Upvotes: 5

flq
flq

Reputation: 22859

The real difference will become apparent when you do this...

public static void SetStudent( ref Student student )
{
    student = new Student { Age = 69, Name="Botox" };
}
...
var a = new Student()
var b = a;
SetStudent(ref a);
object.ReferenceEquals(a, b) // Should be false

Upvotes: 0

Fredrik Mörk
Fredrik Mörk

Reputation: 158399

When you pass an object to a method using the ref key word, the called method can update the reference itself, not only the object. That means that in the following code snippet:

object a = new object();
SomeMethod(ref a);

...a may be another object instance after the call than it was before the call. If you pass an object without the ref keyword, the called method can update properties and members of the passed object, but cannot replace the object itself with another instance.

Upvotes: 0

Related Questions