• FEATURED

View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# Ch 3 oddity

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

6 replies to this topic

### #1Sammie22  Members

Posted 21 January 2011 - 08:40 PM

I found this a little strange.. Maybe I'm having a brain fart here but in Managing Memory section, the author states:

"When you pass in a reference type, we are actually passing a copy of the reference to the data."

He then states, in regards to the 'ref' keyword:

"We should not use this keyword on reference types because it will actually slow things down..."

Then, in Program.cs for the PerformanceChecker, he has this static method signature:

static void PrintPerformance(string label, ref Stopwatch sw) { ... }

At first I was thinking Stopwatch was a struct, but it is a class. So am I missing something here, or did he just say one thing and do another? There is no reason I see to pass as a reference, as it does not redefine the memory pointer for that reference. It only access the member variables of that object.

### #2kiwibonga  Members

Posted 22 January 2011 - 12:13 AM

I now have the same question.

I googled around and I couldn't find any other evidence that using ref when passing reference-types would "slow things down..." In fact, NOT using it means the reference is copied before being pushed to the stack, so there's actually a (probably completely negligible) performance hit from doing that copy and then destroying it.

Odd, to say the least.

### #3Stotto  Members

Posted 22 January 2011 - 07:01 AM

Using ILDASM (C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\ildasm.exe), you could perform a test to see what the difference is between the two.

Lets say we have a class as follows:

class Foo
{
public int foo1 = 0;
}

And lets say we have two methods:

Foo3 (not using the ref keyword)
static void FooMethod3(Foo foo)
{
foo.foo1 = 3;
}

Foo4 (using the ref keyword)
static void FooMethod4(ref Foo foo)
{
foo.foo1 = 4;
}

So lets take a look at the CIL code using ILDASM to see what is going on behind the scenes:

Foo3 (not using the ref keyword)

.method private hidebysig static void  FooMethod3(class RefTest.Foo foo) cil managed
{
// Code size   	9 (0x9)
.maxstack  8
IL_0000:  nop
IL_0001:  ldarg.0
IL_0002:  ldc.i4.3
IL_0003:  stfld      int32 RefTest.Foo::foo1
IL_0008:  ret
} // end of method Program::FooMethod3

And Foo4
.method private hidebysig static void  FooMethod4(class RefTest.Foo& foo) cil managed
{
// Code size   	10 (0xa)
.maxstack  8
IL_0000:  nop
IL_0001:  ldarg.0
IL_0002:  ldind.ref
IL_0003:  ldc.i4.4
IL_0004:  stfld      int32 RefTest.Foo::foo1
IL_0009:  ret
} // end of method Program::FooMethod4

Note: if you optimize these two methods you will just get rid of the nop instruction.

So we can see that Foo4 actually has one more instruction than foo3, called ldind.ref. This instruction is us dereferencing the reference we have made. The rest of the instructions are Identical (well, except for us assigning one a value of 3 and the other a value of 4). There is certainly a performance hit due to one extra operation being performed. But there can be arguments for using the ref keyword with reference types as well.

In the case of the example in the book, I feel that your conclusion is spot on Sammie because as you stated, Stopwatch is not a structure, and only instance-members are accessed, with no re-referencing occurring. There currently is no real need for the ref keyword.

### #4Sammie22  Members

Posted 22 January 2011 - 04:57 PM

Very nice Stotto.. thanks for the reply. And I did not know about that tool, which looks pretty handy.

### #5kiwibonga  Members

Posted 23 January 2011 - 11:19 AM

Thanks for the explanation!

Unfortunately, I'm still confused... Why is it that feeding the reference "directly" requires it to be dereferenced, but feeding a copy of it doesn't?

### #6Stotto  Members

Posted 23 January 2011 - 12:40 PM

Kiwi, I think your confusion lies within how the ref keyword actually operates.

Okay, so as we know:

When a value-type is stored, we store the value.
When a reference-type is stored, we store the contents of the type else-where, and in the reference-type, store a pointer to where those contents are located.

Now, when we don't use the ref keyword:

When a value-type is passed in, we pass in a a copy of that value.
When a reference-type is passed in, we pass a copy of the pointer to where the contents are located.

Using the ref keyword:

When a value-type is passed in, we pass in a pointer to where the value is located.
When a reference-type is passed in, we pass in a pointer to where the reference-type is located. That is to say, we pass in a pointer TO the pointer of where the contents are located.

This may seem odd at first, but I will explain why it is done.

Lets say we have two objects, Foo1 and Foo2. Perhaps we want to make a method that will make Foo1 point to Foo2's contents.

So what we want to do is change the pointer in Foo1 to equal the pointer in Foo2. If we only pass in the locations of the contents, but not the locations of the pointers, we wouldn't be able to do this! We couldn't set the pointer in Foo1 to Foo2 because we do not know where the pointer in Foo1 is located.

By passing in a reference to the reference-type, we now now know where the pointers are located. And because of that we also know their contents, though indirectly. We have to follow the first pointer, to the second, which will lead us to the contents. This is why the dereferencing needs to occur when you are accessing a reference-type's members with the ref keyword.

I hope this helped explain that a little better for you. And if you need further explanation feel free to ask.

### #7kiwibonga  Members

Posted 23 January 2011 - 11:26 PM

Thanks for taking the time to write all that -- I get it now!

Still learning C# for the workshop...

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.