Home > C#, lambdas > Pointers to Value-Types in C#

Pointers to Value-Types in C#

C# has an "unsafe" mode in which real, nasty pointers are allowed, but this mode is rarely used except in some messy situations involving talking to old code. The C# language proper does not have pointers.

In C and C++, you can get the address of anything, including a local variable on the stack:

int x = 0;

int *p = &x; /* get address of x */

*p = 5; /* change value of x */

Of course, when a function exits, all its local variables cease to exist. Any remaining pointers to them are now "dangling" and must not be used. If they ever are… well, who knows what could happen? Make no mistake, it’s an exciting world of opportunities and I’ve already had plenty of it, thanks.

Naturally we’re all very happy not to have such nonsense in C#. But in fact, thanks to anonymous delegates, we can sort of almost do the same thing anyway. But without the undefined behaviour.

Here’s the Ptr<T> generic class, which is a pointer – or at least can be a pointer if you construct it the right way:

public class Ptr<T>
{
    Func<T> getter;
    Action<T> setter;

    public Ptr(Func<T> g, Action<T> s)
    {
        getter = g;
        setter = s;
    }

    public T Deref
    {
        get { return getter(); }
        set { setter(value); }
    }
}

And here’s how to use it:

int x = 0;

Ptr<int> p = new Ptr<int>(() => x, v => x = v); // &x

p.Deref = 5; // *p = 5

Debug.Assert(p.Deref == 5); // *p == 5

In practice it’s a good deal more flexible than a C/C++ pointer. When we construct it, we get to specify exactly how to get or set the value, so there are an unlimited number of possible behaviours, but if we want pointer-like behaviour, we just need to replicate the pattern shown above, providing a getter that maps no arguments onto the variable’s value, and a setter than maps one argument onto the assignment operation.

Using the pointer to modify or obtain the pointed-to value is much simpler. Instead of putting an asterisk in front, we put .Deref on the end.

It’s tempting to think we could add another constructor like this:

public Ptr(ref T x)
{
    getter = () => x;
    setter = v => x = v;
}

… which would allow this:

Ptr<int> p = new Ptr<int>(ref x);

But lambdas are not allowed to refer to ref parameters.

I find it interesting that, thanks to anonymous delegates,  C# already contains the plumbing necessary to implement the & (address-of) operator. It could in theory be done as mere syntactic sugar:

Ptr<int> p = &x;

… which would expand to this:

Ptr<int> p = new Ptr<int>(() => x, v => x = v);

Nothing else is really needed.

(Although to be honest, in the year or so I’ve been using C# in earnest, I haven’t ever needed to take the address of a local value-type.)

About these ads
Categories: C#, lambdas Tags: ,
  1. Colin Eberhardt
    May 29, 2009 at 9:03 am

    Very neat …. I like it :-)

  2. Spencer
    October 1, 2009 at 8:47 pm

    I’m using:
    public delegate T getter();
    public delegate void setter(T value);
    instead of:
    Func getter;
    Action setter;
    but the idea is the same.

    I know this article is old, but mind adding an example on how to implement:
    Ptr p = &x;

    Thanks

  3. earwicker
    October 1, 2009 at 9:09 pm

    Sorry if the article was misleading, but it isn’t possible to make the &x syntax produce a working Ptr. You have to write a lambda that refers to x. The compile silently rewrites your code so that the lambda body is a method in an auto-generated class, and x becomes a field in that class (instead of a local variable on the stack).

    In my post I was just suggesting that in theory the language could be enhanced to have a purely safe version of pointer-to-local semantics, with a little syntactic sugar to expand &x into the required lambda stuff.

  1. April 27, 2014 at 10:04 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: