3

Hi I'm trying to do a simple swap of two objects.My code is

void Main()
{
  object First = 5;
  object Second = 10;

  Swap(First, Second);
  //If I display results it displays as 
  //Value of First as 5 and Second as 10
}

private static void Swap(object First, object Second)
{
  object temp = First;
  First = Second;
  Second = temp;
}

Since objects are reference type, its reference should be passed to method and it should swap. why is it not happening?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Umesh CHILAKA
  • 1,466
  • 14
  • 25
  • 1
    recommend you read http://www.yoda.arachsys.com/csharp/parameters.html to understand what is happening here as the terminology is very important (and wrong in half the answers below). – fearofawhackplanet May 20 '11 at 11:12

7 Answers7

6

Look at it this way.

Let's rename the parameters in your swap method as "x" and "y", because making them the same as the locals is just confusing.

You have an apple and an orange. Two objects.

You have two pieces of paper that say "APPLE" and "ORANGE". Those are references to the objects.

You have two boxes, one labelled First and one labelled Second.

You put "APPLE" in First and "ORANGE" in second.

Now you obtain two more boxes labelled x and y.

You make a photocopy of APPLE and put it in x. You make a photocopy of ORANGE and put it in y.

Now you swap the contents of x and y. APPLE and ORANGE are still references, but you didn't change the contents of First and Second. You changed the contents of x and y.

Now suppose you add "ref" to the declarations of parameters x and y. This now means:

You have two boxes, one labelled First and one labelled Second.

You put "APPLE" in First and "ORANGE" in second.

You add a new label to box First; it may now also be called x. And Second may also be called y.

You swap the contents of x and y. Since they are just aliases for First and Second, the contents of First and Second are swapped.

Make sense?

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
5

There's various different things here:

  • the objects live off in the heap. Forget about them for now
  • the references to the objects are what get stored in First and second
  • you have two variables in Main
  • you have two parameters in Swap

now; the important thing is the difference between "reference type / references", and "pass by reference". They are completely unrelated.

in the line:

Swap(First, Second);

you pass the values of two variables to Swap. In this case, the value of First / Second is the reference to the boxed object.

Next;

private static void Swap(object First, object Second)
{
  object temp = First;
  First = Second;
  Second = temp;
}

Here, you swap the value of two local parameters, but these are completely independent to anything else. If we want the caller to see the change to the values (i.e. reassignment), we need to pass by reference:

private static void Swap(ref object First, ref object Second)
{
  object temp = First;
  First = Second;
  Second = temp;
}

Now the value of First is no longer a reference to the boxed object; it is a reference to a reference to the boxed object. At the caller, we use:

Swap(ref First,ref Second);

which means pass the reference of variable First, rather than pass the value of variable First.

Note that I said you could forget about the fact that there is an object? Everything above is exactly the same if we used:

int x = 1, y = 2;
Swap(ref x, ref y);
void Swap(ref int a, ref int b) {
    var tmp = a; a = b; b = tmp;
}

the only difference is that the value of x is 1 etc, and ref x is a reference to variable x. In pass by reference, reference-type vs value-type is completely irrelevant; the only important thing is understanding that you pass the value of a variable by default, where the value of a variable is 1 (etc), or "a reference to an object". Either way, the logic is the same.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • if I have to pass as ref obj what is difference betwen value type and reference type – Umesh CHILAKA May 20 '11 at 11:23
  • @Chikaka - this might sound circular, but "value-type semantics vs reference-type semantics". By which I mean: does a **standard** *variable*/*parameter* contain a: the *value itself* (value-type), or b: *a reference to an object* (reference-type). As a side effect of that: multiple variables can refer to the ***same*** reference-type, where-as with value-types the struct is copied every time you assign it. In your case you have a boxed object, which is reference-type. But the key here is that your Swap *reassigns* the parameters. To observe that, you need pass-by-reference. – Marc Gravell May 20 '11 at 11:34
  • class GraphPoint { public int X { get; set; } public int Y { get; set; } } void button1_Click(object sender, EventArgs e) { GraphPoint First = new GraphPoint() { X = 1, Y = 1 }; GraphPoint Second = new GraphPoint() { X = 2, Y = 2 }; Mofiy(First); //If I display results it displays //Value of First as 5 } void Mofiy(GraphPoint First) { First.X = 5; First.Y = 5; } if it is not passing reference, how does values of First changes in Main after call of modify method. – Umesh CHILAKA May 20 '11 at 11:49
  • @Chilaka - note I used the word *reassign* twice? The key is that in `Swap` you **give the parameters different values** - `First = ...`. In the example you've just given, you merely *change properties of the object*. Note that *where the change happens* is now completely different - the *reference* (the value of the parameter) is unchanged, but the far away object on the heap is changed. If you are just changing the object, the caller sees that automatically - after all, it ***is the same object***. – Marc Gravell May 20 '11 at 11:53
  • Thanks for helping me to understand it better. – Umesh CHILAKA May 20 '11 at 12:02
1

The object pointed to by the parameters inside the Swap method are references to the First and Second objects inside Main, but the parameters themselves are local to the Swap method.

So if you inside Swap had written First = 1; Second = 2;, you would have seen the change in the objects inside Main. However, you only change what the paremeters to Swap point to (by assigning them to another object), and do not change the objects at all. The same would be true if you tried setting the objects to null inside the Swap method.

Øyvind Bråthen
  • 59,338
  • 27
  • 124
  • 151
1

You are not passing it as a reference, you need to explicitly state that you are passing the reference:

 Swap(ref First,ref Second);

 private static void Swap(ref object First,ref object Second)
TBohnen.jnr
  • 5,117
  • 1
  • 19
  • 26
  • If I have to pass explicitly by ref keyword. Then wat is difference between vale type and reference type – Umesh CHILAKA May 20 '11 at 11:25
  • Because it's in another method you have to explicitly say you want to pass the reference, where as if it was in the same method it would work. Most of the time though you will not need to pass the refererence and would only want to pass the value of the object and that is why you have to specify it ass a reference – TBohnen.jnr May 20 '11 at 11:27
  • just try this class point{public int X;} now pass object of class point to other method(say modify) and change its X value in this function. In your main method after modify method, check the value of X it would have changed(don't pass by ref). How is this happening? – Umesh CHILAKA May 20 '11 at 11:34
  • I would assume this is a case of deep copying vs shallow copying, have a look here: http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy To add to your modify method, assign the point class to a new point class and then change the value of X, you will now see that it did not change the value of the initial class – TBohnen.jnr May 20 '11 at 11:45
  • I would however suggest you pose that question to @Mark Gravell so that he can confirm this – TBohnen.jnr May 20 '11 at 11:45
1

Rather than passing the references to the objects by value you need to pass them by reference. In other words, you need to pass a reference to the reference to the object.

This is achieved using the ref keyword.

E.g.

private static void Swap(ref object First, ref object Second)
{
  object temp = First;
  First = Second;
  Second = temp;
}
Nick
  • 25,026
  • 7
  • 51
  • 83
1

You're passing the reference to the objects by value (pass by value is the default in C#).

Instead, you need to pass the objects to the function by reference (using the ref keyword).

private static void Swap(ref object first, ref object second)
{
    object temp = first;
    first = second;
    second = temp;
}

void Main()
{
    object first = 5;
    object second = 10;

    Swap(ref first, ref second);
}

Of course, if you're using C# 2.0 or later, you would do better to define a generic version of this function that can accept parameters of any type, rather than the object type. For example:

private static void Swap<T>(ref T first, ref T second)
{
    T temp;
    temp = first;
    first = second;
    second = temp;
}

Then you could also declare the variables with their proper type, int.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
0

You need to pass by reference.

Here's some extra info on pass-by-refence, pass-by-value: http://www.yoda.arachsys.com/csharp/parameters.html, try this:

void Main()
{
 object First = 5;
 object Second = 10;

  Swap(ref First, ref Second);
  //If I display results it displays as 
  //Value of First as 5 and Second as 10
}


private static void Swap(ref object First, ref object Second)
{
  object temp = First;
  First = Second;
  Second = temp;
}
RubenHerman
  • 1,674
  • 6
  • 23
  • 42