views:

656

answers:

7

I just made a Swap routine in C# like this:

static void Swap(ref int x, ref int y)
{
    int temp = x;
    x = y;
    y = temp;
}

It does the same thing that this C++ code does:

void swap(int *d1, int *d2)
{
    int temp=*d1;
    *d1=*d2;
    *d2=temp;
}

So are the ref and out keywords like pointers for C# without using unsafe code?

+5  A: 

Reference parameters in C# can be used to replace one use of pointers, yes. But not all.

Another common use for pointers is as a means for iterating over an array. Out/ref parameters can not do that, so no, they are not "the same as pointers".

jalf
+5  A: 

They're more limited. You can say ++ on a pointer, but not on a ref or out.

It's a safe bet that they are internally just pointers, because the stack doesn't get moved and C# is carefully organised so that ref and out always refer to an active region of the stack.

If you ever play with interop in unsafe code, you will find that ref is very closely related to pointers. For example, if a COM interface is declared like this:

HRESULT Write(BYTE *pBuffer, UINT size);

The interop assembly will turn it into this:

void Write(ref byte pBuffer, uint size);

And you can do this to call it (I believe the COM interop stuff takes care of pinning the array):

byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);

In other words, ref to the first byte gets you access to all of it; it's apparently a pointer to the first byte.

Daniel Earwicker
+1  A: 

The short answer is Yes (similar functionality, but not exactly the same mechanism). As a side note, if you use FxCop to analyse your code, using out and ref will result in a "Microsoft.Design" error of "CA1045:DoNotPassTypesByReference."

Erich Mirabal
+1  A: 

The nice thing about using out is that you're guaranteed that the item will be assigned a value -- you will get a compile error if not.

bufferz
+2  A: 

Actually, I'd compare them to C++ references rather than pointers. Pointers, in C++ and C, are a more general concept, and references will do what you want.

All of these are undoubtedly pointers under the covers, of course.

David Thornley
Daniel Earwicker
(I mean at the calling site.)
Daniel Earwicker
So they're really somewhere in the middle (as you don't have to dereference it when reading/writing to it).
Pavel Minaev
+2  A: 

ref and out are only used with function arguments to signify that the argument is to be passed by reference instead of value. In this sense, yes, they are somewhat like pointers in C++ (more like references actually). Read more about it in this article.

Saulius
+1  A: 

While comparisons are in the eye of the beholder...I say no. 'ref' changes the calling convention but not the type of the parameters. In your C++ example, d1 and d2 are of type int*. In C# they are still Int32's, they just happen to be passed by reference instead of by value.

By the way, your C++ code doesn't really swap its inputs in the traditional sense. Generalizing it like so:

template<typename T>
void swap(T *d1, T *d2)
{
    T temp = *d1;
    *d1 = *d2;
    *d2 = temp;
}

...won't work unless all types T have copy constructors, and even then will be much more inefficient than swapping pointers.

Richard Berg
I don't think your analogy quite works; consider `int *` versus `const int *` in C++. Const is a qualifier that restricts the use of the type it applies to, effectively turning it into a different type. But when C++ is compiled to IL, `const` is turned into a kind of custom modifier on a type rather than defining a different type in the CLI type system. This shows that "type" in the language is separate from "type" in the runtime. In the same way `ref` limits what you can do with the object (you can't capture it in a lambda, for example), and this is part of C#'s type system, though not CLI's.
Daniel Earwicker