Re: Using ref
- From: raylopez99 <raylopez99@xxxxxxxxx>
- Date: Thu, 3 Jul 2008 06:28:18 -0700 (PDT)
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 . . .
.
- Follow-Ups:
- Re: Using ref
- From: Marc Gravell
- Re: Using ref
- From: Jon Skeet [C# MVP]
- Re: Using ref
- References:
- Using ref
- From: Arjen
- Re: Using ref
- From: Steve Harclerode
- Re: Using ref
- From: Jon Skeet [C# MVP]
- Re: Using ref
- From: Steve Harclerode
- Re: Using ref
- From: Jon Skeet [C# MVP]
- Using ref
- Prev by Date: Re: Preserving column names in a data set
- Next by Date: Re: Preserving column names in a data set
- Previous by thread: Re: Using ref
- Next by thread: Re: Using ref
- Index(es):
Relevant Pages
|