ref?

D

Daniel

Hey guys

I need some clarification.

The ref keyword means that you pass in a reference to an object or variable,
is it like the & and * of c++?

What i don't understand is, in c#, it always uses reference by i thought,
or is it only refs on classes?

so if i do

someobj so = new someObj(); //so memory allocated

so.someVar = 10; //somevar set to 10

someobj so2 = so; //they now equal each other, so2 is using a ref as we did
not clone it

so2.someVar = 20; //when we do this, so.someVar also becomes 20

Console.Writeline(so.someVar.ToString());

//would print out 20

Isn't that right? If that is the case, why the ref keyword and when would
you need it?
 
F

ForrestPhoto

What i don't understand is, in c#, it always uses reference by i thought,
or is it only refs on classes?

Memory is allocated on the stack and the heap; this translates to
primitive "value types" and "reference types." An integer or boolean
is stored by value, whereas instances of classes are created with the
new keyword and then managed by reference, where in your code you have
to variables that are both references to the same object in memory, and
when one makes a change, the other will see it.

Counter-intuitively, though, structs are value types. So if you use "x
= y;" in your code you're cloning the values, not using two pointers to
the same location.
 
Y

Yota

'ref' and 'out' are used with method params. Here are some examples
that should get the idea across..

void Test1(int val)
{
val++;
}
void Test2(ref int val)
{
val++;
}
void Test3(out int val)
{
val++;
}


int myInt = 5;

Test1(myInt);
// myInt still equals 5.
// The procedure modified its own copy of the data.

Test2(ref myInt); // The 'ref' is nessisary here.
// myInt now equals 6.
// The procedure was given a reference to the 'myInt' var directly.

Test3(out myInt); // The 'out' is nessisary here as well.
// myInt now equals 1.
// The procedure was given a fresh new reference, but 'myInt' was
replaced with that new reference.
 
D

Dave Sexton

Hi,

The ref keyword is used for passing method arguments by reference and has
nothing to do with property or field assignment. It's observable behavior
is the same for value-types and reference types, however, the reasons for it
are somewhat less trivial.

In the code below, "localVar", a System.Boolean, is a value type. Passing
it in by-reference is like passing in a pointer to the location of the
variable within the TestRef method.

void TestRef()
{
bool localStruct = false;

UpdateMyLocalVariable(ref localStruct);

Console.WriteLine(localStruct); // true
}

void UpdateMyLocalVariable(ref bool localStruct)
{
// update the reference to localStruct
// so that *it is* a new value
localStruct = true;
}

In the following code an object reference is updated. Note, it's the
reference that is being passed by-reference, not what it normally points to,
which is the actual location of the object in memory.

void TestRefObject()
{
object localObject= new object();

UpdateMyLocalVariable(ref localObject);

Console.WriteLine(localObject); // "A string object";
}

void UpdateMyLocalVariable(ref object localObject)
{
// update the reference to localObject
// so *it points to* a string (which is an object)
localObject = "A string object";
}


When you pass a value by-reference you're passing in a reference to the
value where it exists on the stack or the heap, not a copy as is
traditionally sent for value-types.

When you pass an object by-reference you're passing in the reference itself,
not what it points to - the object. Traditionally, when you pass an object,
you're passing in the location of the object on the heap. By-ref, you're
passing in the reference to the location on the heap instead.
 
J

Jon Skeet [C# MVP]

Memory is allocated on the stack and the heap; this translates to
primitive "value types" and "reference types."

No, it doesn't.

See http://www.pobox.com/~skeet/csharp/memory.html
An integer or boolean is stored by value, whereas instances of
classes are created with the new keyword and then managed by
reference, where in your code you have to variables that are both
references to the same object in memory, and when one makes a change,
the other will see it.

Counter-intuitively, though, structs are value types. So if you use "x
= y;" in your code you're cloning the values, not using two pointers to
the same location.

Why is that counter-intuitive for you, out of interest?
 
C

ChrisM

In message (e-mail address removed),
Jon Skeet said:
No, it doesn't.

See http://www.pobox.com/~skeet/csharp/memory.html


Why is that counter-intuitive for you, out of interest?

Maybe not counter-intuitiave, but slightly confusing at times. It can
sometimes not be clear straight away if you are dealing with a class or a
struct, especially if you are reading a large chunk of someone elses code.
Then again, what is the logical reason for structs behaving differently in
this way?
 
G

Gary

Hi jon thanks for the article it was very helpful.

Do you happen to have an article which explains what the stack/heap is,
or know of any good article that does likewise?

Thanks,

Gary.
 
J

Jon Skeet [C# MVP]

ChrisM said:
Maybe not counter-intuitiave, but slightly confusing at times. It can
sometimes not be clear straight away if you are dealing with a class or a
struct, especially if you are reading a large chunk of someone elses code.
Then again, what is the logical reason for structs behaving differently in
this way?

The whole point of having structs and classes is to have both value
type behaviour and reference type behaviour. When you want a type to
behave with reference type semantics, use a class. When you want a type
to behave with value type semantics, use a struct.

It's very, very rare to want to define your own value type - usually
you'll be using the predefined value types (int etc, Guid, DateTime...)
 
J

Jon Skeet [C# MVP]

Gary said:
Hi jon thanks for the article it was very helpful.

Do you happen to have an article which explains what the stack/heap is,
or know of any good article that does likewise?

I don't know of a good article, I'm afraid.
 
B

Bill Butler

Daniel said:
Hey guys

I need some clarification.

The ref keyword means that you pass in a reference to an object or
variable, is it like the & and * of c++?

The closest thing to the ref keyword in C# would be **.
Not only can you modify the object, you can replace the object with a
new object.

Bill
 
B

Bruce Wood

Yota said:
'ref' and 'out' are used with method params. Here are some examples
that should get the idea across..

void Test1(int val)
{
val++;
}
void Test2(ref int val)
{
val++;
}
void Test3(out int val)
{
val++;
}


int myInt = 5;

Test1(myInt);
// myInt still equals 5.
// The procedure modified its own copy of the data.

Test2(ref myInt); // The 'ref' is nessisary here.
// myInt now equals 6.
// The procedure was given a reference to the 'myInt' var directly.

Test3(out myInt); // The 'out' is nessisary here as well.
// myInt now equals 1.
// The procedure was given a fresh new reference, but 'myInt' was
replaced with that new reference.

Method Test3 won't even compile: the "out" modifier indicates that
"val" can be passed in without being initialized, and incrementing an
uninitialized variable is a no-no. Test3 would have to be written like
this:

void Test3(out int val)
{
val = 0;
val++;
}

or something like that.
 
F

ForrestPhoto

Counter-intuitively, though, structs are value types. So if you use "x
Why is that counter-intuitive for you, out of interest?

Because structs aren't primatives, and because you can write an
initializer, and then (seemingly) create instances of the struct. My
thinking is that creating an instance means allocating a slot of memory
and populating it ... then accessing it later through a pointer. I
realize that type initializers in structs are there for convenience, to
set a bunch of values with one line of code, but in practice ... it
just seems counter-intuitive to me.
 
C

Christof Nordiek

Hi Daniel,

the ref and out keyword means you are passing a variable instead of a value
resp. an object.
So the called method will be able to assign to the variable given by the
caller.

A parameter without ref or out is like a local variable, wich is assigned by
the caller.
 
J

Jon Skeet [C# MVP]

Because structs aren't primatives, and because you can write an
initializer, and then (seemingly) create instances of the struct.

Yup - but they're still value types.
My thinking is that creating an instance means allocating a slot of memory
and populating it ... then accessing it later through a pointer.

That thinking is what's wrong.
I realize that type initializers in structs are there for convenience, to
set a bunch of values with one line of code, but in practice ... it
just seems counter-intuitive to me.

Do you have a C++ background? If so, maybe it's a "new implies
pointer" instinct.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top