What is the difference between a C# Reference and a Pointer?

42,617

Solution 1

C# references can, and will be relocated by garbage collector but normal pointers are static. This is why we use fixed keyword when acquiring a pointer to an array element, to prevent it from getting moved.

EDIT: Conceptually, yes. They are more or less the same.

Solution 2

There is a slight, yet extremely important, distinction between a pointer and a reference. A pointer points to a place in memory while a reference points to an object in memory. Pointers are not "type safe" in the sense that you cannot guarantee the correctness of the memory they point at.

Take for example the following code

int* p1 = GetAPointer();

This is type safe in the sense that GetAPointer must return a type compatible with int*. Yet there is still no guarantee that *p1 will actually point to an int. It could be a char, double or just a pointer into random memory.

A reference however points to a specific object. Objects can be moved around in memory but the reference cannot be invalidated (unless you use unsafe code). References are much safer in this respect than pointers.

string str = GetAString();

In this case str has one of two state 1) it points to no object and hence is null or 2) it points to a valid string. That's it. The CLR guarantees this to be the case. It cannot and will not for a pointer.

Solution 3

A reference is an "abstract" pointer: you can't do arithmetic with a reference and you can't play any low-level tricks with its value.

Solution 4

A major difference between a reference and a pointer is that a pointer is a collection of bits whose content only matters when it is actively being used as a pointer, while a reference encapsulates not only a set of bits, but also some metadata which keeps the underlying framework informed of its existence. If a pointer exists to some object in memory, and that object is deleted but the pointer is not erased, the pointer's continued existence won't cause any harm unless or until an attempt is made to access the memory to which it points. If no attempt is made to use the pointer, nothing will care about its existence. By contrast, reference-based frameworks like .NET or the JVM require that it always be possible for the system to identify every object reference in existence, and every object reference in existence must always either be null or else identify an object of its proper type.

Note that each object reference actually encapsulates two kinds of information: (1) the field contents of the object it identifies, and (2) the set of other references to the same object. Although there isn't any mechanism by which the system can quickly identify all the references that exist to an object, the set of other references that exist to an object may often be the most important thing encapsulated by a reference (this is especially true when things of type Object are used as things like lock tokens). Although the system keeps a few bits of data for each object for use in GetHashCode, objects have no real identity beyond the set of references that exist to them. If X holds the only extant reference to an object, replacing X with a reference to a new object with the same field contents will have no identifiable effect except to change the bits returned by GetHashCode(), and even that effect isn't guaranteed.

Solution 5

Pointers point to a location in the memory address space. References point to a data structure. Data structures all moved all the time (well, not that often, but every now and then) by the garbage collector (for compacting memory space). Also, as you said, data structures without references will get garbage collected after a while.

Also, pointers are only usable in unsafe context.

Share:
42,617
Richard
Author by

Richard

Updated on January 18, 2020

Comments

  • Richard
    Richard over 4 years

    I do not quite understand the difference between a C# reference and a pointer. They both point to a place in memory don't they? The only difference I can figure out is that pointers are not as clever, cannot point to anything on the heap, are exempt from garbage collection, and can only reference structs or base types.

    One of the reasons I ask is that there is a perception that people need to understand pointers well (from C, I guess) to be a good programmer. A lot of people who learn higher level languages miss this out and therefore have this weakness.

    I just don't get what is so complex about a pointer? It is basically just a reference to a place in memory is it not? It can return its location and interact with the object in that location directly?

    Have I missed a massive point?

  • Richard
    Richard over 15 years
    Isn't there another command that prevents a C# reference from having the object it's reference moved by the GC?
  • Richard
    Richard over 15 years
    Oh sorry, I thought it was something else because the post referred to a pointer.
  • ctacke
    ctacke over 15 years
    Yes, a GCHandle.Alloc, or a Marshal.AllocHGlobal (beyond fixed)
  • mmx
    mmx over 15 years
    It's fixed in C#, pin_ptr in C++/CLI
  • mmx
    mmx over 15 years
    Marshal.AllocHGlobal will not allocate memory in managed heap at all and naturally it's not subject to garbage collection.
  • Richard
    Richard over 15 years
    The array thing sounds interesting, is that basically where you can tell the pointer to offset the memory location like an array while you are unable to do this with a reference? Can't think when that would be useful but interesting none the less.
  • P Daddy
    P Daddy over 15 years
    If p is an int* (a pointer to an int), then (p + 1) is the address identified by p + 4 bytes (the size of an int). And p[1] is the same as *(p + 1) (that is, it "dereferences" the address 4 bytes past p). By contrast, with an array reference (in C#), the [] operator performs a function call.
  • Glenn Slayden
    Glenn Slayden over 12 years
    A minor quibble that perhaps you shouldn't say "managed pointer" here--even with scare quotes--because this is something quite different from an object reference, in IL. Although there is syntax for managed pointers in C++/CLI, they are generally not accessible from C#. In IL, they are obtained with the (i.e.) ldloca and ldarga instructions.
  • supercat
    supercat over 10 years
    Personally, I think C# would have been a better language if most places that use . used ->, but foo.bar(123) was synonymous with a call to static method fooClass.bar(ref foo, 123). That would have allowed things like myString.Append("George"); [which would modify the variable myString], and made more obvious the difference in meaning between myStruct.field = 3; and myClassObject->field = 3;.