Re: Using ref



On Jul 2, 10:46 pm, "Jon Skeet [C# MVP]" <sk...@xxxxxxxxx> wrote:

So consider this code:

public void Swap (object a, object b)
{
    object tmp = a;
    a = b;
    b = a;

}

If the parameter were passed by reference by default, that would work.
As it is, it does nothng.

This example is totally wrong Jon. You probably meant to write
"b=tmp;"
And you call yourself a "[C# MVP]"? Well, I can call myself an "C#
N00b MVP" then.

But we all make mistakes--in my previous post in this thread, I stated
'ref' is only needed when objects are passed if the calling method
uses 'new'--this is not strictly speaking true, as evidenced by the
line by Jon above "object tmp = a;". (Though, to be pedantic, "object
tmp = new object(); tmp = a;" would also work, but not be as concise
and fast).

To demonstrate that for most stuff, except for swap, 'new' and stuff
where you are redirecting the references, I wrote a short program
below to show when to use 'ref' and pass-by-reference for reference-
types (objects, strings) and when to not use 'ref' and just rely on
pass-by-value for reference-types, which usually for most stuff gives
the same result.

As you can see for the string (a reference type) passing by reference
is the same as passing by value when changing the string--and outside
the method the string *is* changed. However, if 'new' were involved,
it would be different.

You can see this by looking at the StringBuilder methods below--one is
pass-by-value, and the other is pass-by-reference. Both 'do stuff' to
the strings that are persistent--even outside the methods--for example
X.Append("SB1") changes the string in the pass-by-value method. But
when 'new' is involved, you must pass-by-reference when passing a
reference-type parameter (such as a string, an array, an object).

In the second example, the traditional "swap" method is demonstrated,
which shows again why 'ref' keyword is needed to make such a
'redirection' of objects and/or references to objects persistent
outside the method.

Ray Lopez
[C# N00b MVP]
-
using System;
using System.Collections.Generic;
using System.Text;

namespace ParaPassingPassByValByRef_01
{
class Program
{
static void Main(string[] args)
{
StringBuilder mainY = new StringBuilder();
mainY.Append("Hellow");
Console.Write("Output of mainY is true or false?...");
Console.WriteLine(mainY != null);
Console.WriteLine("value of string mainY is:{0}", mainY);
// mainY = null; //causes runtime error!
mainY.Append(" ");

// ignore the next few lines dealing with mainY2--it's an
attempt to see if a string can be set to null

StringBuilder mainY2 = new StringBuilder ("");
mainY2 = null;

Console.Write("..................");

//mainY2.Append("hello2");
//Console.WriteLine("str hello2: {0}", mainY2);

Console.WriteLine(mainY2 == null); //it's dangerous to do
anything but check for this condition when setting an object to
'null' (runtime error)
// end of mainY2

FooClass1 myFC1 = new FooClass1();
myFC1.FooClassSB1(mainY);
Console.WriteLine("mainY after SB1 is: {0}, int is: {1}",
mainY, myFC1.j);
myFC1.FooClassSB2(ref mainY);
Console.WriteLine("mainY after SB2 is: {0}, int is: {1}",
mainY, myFC1.j);
// myFC1.FooClassSB1(mainY2); //dangerous!: compiles but
gives runtime error

AClass1 A = new AClass1();
A.Aint = 111;
AClass1 B = new AClass1();
B.Aint = 222;
Console.WriteLine("main A,B before swap: {0}, {1}",
A.Aint, B.Aint);
myFC1.Swap(ref A, ref B);

Console.WriteLine("main A,B after swap: {0}, {1}", A.Aint,
B.Aint);
Console.WriteLine("................");
Console.WriteLine("reset back to A=111, B=222");
A.Aint = 111; B.Aint = 222;
Console.WriteLine("main A,B before swap2: {0}, {1}",
A.Aint, B.Aint);
myFC1.Swap2(A, B);

Console.WriteLine("main A,B after swap2: {0}, {1}",
A.Aint, B.Aint);

}
}
}


//////////////////////
using System;
using System.Collections.Generic;
using System.Text;

namespace ParaPassingPassByValByRef_01
{
class FooClass1
{
public FooClass1()
{
j = 101;
}
public int j;

public void FooClassSB1(StringBuilder x)
{
x.Append("SB1");
Console.WriteLine("inside FCSB1, part I: {0}", x);
j = j + 123;
StringBuilder temp = new
StringBuilder("temp_string_local_only!");
x = temp;
Console.WriteLine("inside FCSB1, part II: {0}", x);
}
public void FooClassSB2(ref StringBuilder x)
{
x.Length = 0; //this truncates [sets] string to zero
length (nice feature)
x.Append("SB2!");
Console.WriteLine("inside FCSB2, part I: {0}", x);
j = 22222;

StringBuilder temp = new
StringBuilder("temp_string_NOT_just_local_only!");
x = temp;
Console.WriteLine("inside FCSB2, part II: {0}", x);

}

public void Swap(ref AClass1 a, ref AClass1 b)
{
AClass1 temp = a; //no need for ‘new’ for temp
instantiation
Console.WriteLine("inside Swap a: {0}", a.Aint);
a = b;
Console.WriteLine("inside Swap a, b, before b swap: {0},
{1}", a.Aint, b.Aint);
b = temp;
Console.WriteLine("inside Swap a,b, after swap: {0}, {1}",
a.Aint, b.Aint);

}

public void Swap2(AClass1 a, AClass1 b)
{
// this version, Swap2, does not get the job done since 'ref' not
being used
AClass1 temp = new AClass1();
temp = a;
Console.WriteLine("inside Swap2 a: {0}", a.Aint);
a = b;
b = temp;
Console.WriteLine("inside Swap2 a,b, after swap: {0},
{1}", a.Aint, b.Aint);

}


}
}

/*

*/
/////////////////////////////////
using System;
using System.Collections.Generic;
using System.Text;

namespace ParaPassingPassByValByRef_01
{
class AClass1
{
public int Aint;

}
}

////////////////////////////////

// OUTPUT

Output of mainY is true or false?...True
value of string mainY is:Hellow
..................True
inside FCSB1, part I: Hellow SB1
inside FCSB1, part II: temp_string_local_only!
mainY after SB1 is: Hellow SB1, int is: 224
inside FCSB2, part I: SB2!
inside FCSB2, part II: temp_string_NOT_just_local_only!
mainY after SB2 is: temp_string_NOT_just_local_only!, int is: 22222
main A,B before swap: 111, 222
inside Swap a: 111
inside Swap a, b, before b swap: 222, 222
inside Swap a,b, after swap: 222, 111
main A,B after swap: 222, 111
................
reset back to A=111, B=222
main A,B before swap2: 111, 222
inside Swap2 a: 111
inside Swap2 a,b, after swap: 222, 111
main A,B after swap2: 111, 222
Press any key to continue . . .
.



Relevant Pages

  • Re: passing value from jcombobox to other classes?
    ... public void setX(String x) { ... // the reference to an object of A ... Run it by "java C" and see what happens. ...
    (comp.lang.java.programmer)
  • Re: pass by reference
    ... fields in the reference does reflect the changes. ... should not try to understand java in a C++ manner. ... but i can't help, String is a object, so a reference should be the one ... public void myFunc{ ...
    (comp.lang.java.programmer)
  • Re: Problems with TIB again, I think
    ... parse dup>r ... swap cmove (move string to one cell after here) ... r> allot align (get count and allocate mem for string, ...
    (comp.lang.forth)
  • [PATCH for mmotm] remove pagevec_swap_free()
    ... that happen to be on the pagevec after the deactivation loop. ... Complete 7e9cd48 and remove the rest of the swap freeing. ... * The caller needs to hold an extra reference to each page and ...
    (Linux-Kernel)
  • Re: PreparedStatement across classes
    ... I'll check out the reference. ... > static class level variable will remain as null. ... >> public void endElement(String uri, String localName, String qName) ... >> public void notationDecl ...
    (comp.lang.java.databases)