How to use managed pointers in C#

Learn how managed pointers differ from object references, why they are useful, and how to work with them in C#

How to use managed pointers in C#
Thinkstock

A pointer is a variable that points to the address of another variable. In other words, a pointer holds the memory address of another variable or a memory location. Until recently, the only way to work with pointers in C# was by using unsafe code. You could take advantage of the unsafe keyword to define an unsafe context and then create unmanaged pointers or invoke native functions using unmanaged pointers.

It should be noted here that unsafe code implies code that is executed outside of the context of the CLR. It is unmanaged code. However, since you are turning off the safety provided by the CLR by default, it is advisable that you use unsafe code only if you are aware of how memory management works in .Net.

An object reference in C# is a type-safe pointer that points to the beginning of an object. There is another type of pointer in the CLR known as a managed pointer. This article examines what managed pointer are, why they are useful, and how we can work with them in C#.

Managed pointers in C# explained

A managed pointer differs from a type-safe pointer in being able to point to other locations of an object, i.e., not just the beginning of the object. Like an object reference, a managed pointer can point to objects stored in the managed heap. The difference is that, while an object reference points to the beginning of the object, a managed pointer can point to method parameters, fields, array elements, or any other part of the object.

In essence, a managed pointer can point to the following:

  • a local variable
  • an element of an array
  • a method parameter
  • a field of a compound type

Managed pointers don’t support pointer arithmetic directly. You can’t “add” or “subtract” the values of the addresses they point to. You cannot box a value of a managed pointer. Apparently, it is because of these limitations that managed pointers are not explicitly exposed in the C# language. However, managed pointers have been implicit in C# for a long time as reference parameters. When you pass a parameter to a method by reference, you are using a managed pointer behind the scenes.

10 rules for using managed pointers in C#

Note the following points on managed pointers.

  1. Managed pointers cannot be null.
  2. It is not possible for a managed pointer to point to another managed pointer.
  3. Managed pointers cannot be on the heap.
  4. You cannot interchange a managed pointer with an object reference.
  5. You cannot store managed pointers in static variables or as elements of an array or field.
  6. You cannot use managed pointers as the element type of an array.
  7. A managed pointer can point to an object reference or a value type.
  8. If you pass a method parameter as a reference, the argument is actually a managed pointer.
  9. Managed pointers are also referred to as byref types.
  10. A managed pointer can point to a local variable of a method or a parameter of a method.

Pass an argument by reference in C#

Okay, we have had enough of the concepts. Let’s now write some code to understand managed pointers. You can use ref parameters, ref locals, or ref returns to represent a managed pointer. Let’s explore each of these one by one.

Consider the following struct that contains just one member, an integer variable.

public struct MyStruct
{
   public int MyField;
}

The following method updates the value of the MyField data member of an instance of MyStruct.

private static void Update(ref MyStruct data)
{
   data.MyField = 5;
}

The following code snippet illustrates how you can pass an argument by reference instead of value.

public int Main()
{
  MyStruct obj = new MyStruct();
  obj.MyField = 1;
  Update(ref obj);
  Console.WriteLine(obj.MyField);
  Console.Read();
}

You can take advantage of structs in lieu of classes to avoid heap allocation and the overhead of copying data. This is a good optimization trick that can be used for structs that have few data members.

When you execute the above program, “5” is displayed at the console window.

Use a ref local to store a managed pointer in C#

You can also use a ref local to store a managed pointer. The following code snippet illustrates how this can be achieved. Note the use of the ref keyword on both sides of the assignment.

public static void UpdateDataUsingRefLocal(MyStruct data)
  {
     ref int refLocal = ref data.MyField;
     refLocal = 10;
  }

You can take advantage of ref returns to return a variable from a method that represents a managed pointer. Note that this cannot be a local variable, i.e., you cannot return a local variable that represents a managed pointer. An attempt to return a local variable will result in a compilation error.

The following code snippet illustrates how ref returns can be used.

public static ref int GetMarksByRef(int[] marks, int subjectIndex)
{
  return ref marks[subjectIndex];
}

Whereas an object reference points to the beginning of an object, a managed pointer can point inside an object, to a field of a type, or to an element of an array. It is interesting to know how managed pointers work behind the scenes. I will discuss how managed pointers work in more detail in a future post here.

Copyright © 2019 IDG Communications, Inc.

How to choose a low-code development platform