1

I've just started learning C# and I really like the concept of the Lists there. I'm just wondering why I can't make the list of pointers. I'm trying to make list of pointers to object of my class, but when I write:

List <MyClass*> mylist;

or even:

List <int*> mylist;

VS shows an error message:

The type 'MyClass*" may not be used as a type argument

I have no idea why. Is there any solution for this or is it completely forbidden to make pointer-type lists?

(sorry for dumb question, I'm just learning stuff)

3
  • 1
    c#, is not c++/c, it's masking the pointers... so you cannot work with pointers, you can manipulate variables by val or by ref (it's kind of pointer) Commented May 28, 2016 at 23:42
  • 1
    @Proxytype Well, you can, you just shouldn't. And passing a value by reference isn't like a pointer in C++, it's exactly like passing a parameter by reference in C++. Both languages have the exact same feature, with the same semantics (but a slightly different syntax). Commented May 29, 2016 at 1:30
  • I was just wondering if I can do such thing and why not (out of curiosity and to learn more). Thank you both for explanation. Commented May 29, 2016 at 9:16

4 Answers 4

4

Pointer types like int* or even MyStruct* (where MyStruct must be a value type with usual layout whose instance fields (recursively) are again value types) do exist in C#, but are not used very often in most applications.

However, pointer types cannot be used as generic type arguments, so the "T" in List<T> is not allowed to be int*. It is OK to have arrays of pointers, like an int*[] or MyStruct*[] for instance.

To answer your question: No, there is no way to use a pointer type for a generic type argument. Note that this is not just a C# limitation, the CLR type system refuses it (e.g. typeof(List<>).MakeGenericType(typeof(int*)) will throw an exception).

Related to that, pointer types do not inherit from object like "normal" concrete types do in the C#/.NET type system.

In C#, pointers are to value types only. With reference type (like a user-defined type declared with class), the "value" of the variable or expression of that type, is a reference (implementation-defined memory location) to the actual instance, or a null reference (refers no instance). These references are somewhat like "pointers", but they do not allow arithmetic (like adding or subtracting memory locations, or converting the "address" to an integer) in the way true pointers like int* and MyStruct* do.

Sign up to request clarification or add additional context in comments.

Comments

1

In C# creating a list of class instances is way simpler then that. You initialize the list with a class or value it's going to store and then add the instances or values.

For instance a list of MyClass instances would be something like this:

List<MyClass> myList = new List<MyClass>();

MyClass myClass1 = new MyClass;
myList.Add(myClass1);

Or for an int:

List<int> myList = new List<int>();
myList.Add(123);    

And that's it. No need for pointers to store instances of a class.

Edit

There is no possibility in C# to have a pointer to a reference type or to a struct type that contains a reference. It is because the garbage collector can collect a reference type even when a pointer points to it. This topic is described in more detail on MSDN Pointer types article. So C# does not allow anything like MyClass*.

Also, in the same article, you can find that the only allowed pointer types are: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.

As to your question about int* as a type argument in List<int*> the documentation says pointer types cannot be used as type arguments. See chapter 18.4.1 for more details.

1 Comment

Yes, I know how to do it. I was just wondering if there is such a possibility and why not (out of curiosity and to learn more). Thank you. :)
0

As mentioned in other answers, you can't use a pointer type as a generic argument. In general pointers in C# are only allowed in "unsafe" sections, and the pointers are unmanaged -- you must handle their creation and destruction yourself. My guess is that the reasons pointers aren't supported in generics is (a) it would be confusing with garbage collection and make it too easy to shoot yourself in the foot, and/or (b) it's just not worth the headache for the language designers since pointers should be very rare in managed code.

However, this does come up a lot in some cases for example when interfacing with legacy C++ code. One useful workaround is the "IntPtr" class. As you've noticed, this won't compile:

   MyClass* foo = ...;
   List <MyClass*> mylist = new List<MyClass*>();
   mylist.Add(foo);
   MyClass* bar = mylist[0];

But you should be able to do an (ugly) workaround by casting the pointers to the IntPtr type:

   MyClass* foo = ...;
   List <IntPtr> mylist = new List<IntPtr>();
   mylist.Add((IntPtr)foo);
   MyClass* bar = (MyClass*)mylist[0];

But again this usually isn't a smart thing to do in purely managed code. Typically I would only do this if I have to interoperate with C++ code and have a bunch of unmanaged structs to keep track of.

Comments

0

This question came up when I searched for "C# list of pointers". In my case I wanted a List<ulong*>. Something like this worked for me:

readonly unsafe struct ULongPointer
{
  public readonly ulong* Value;

  public ULongPointer(ulong* value)
  {
    Value = value;
  }
}

ulong value = 0x123UL;

var listOfULongPointers = new List<ULongPointer>();
unsafe
{
  listOfULongPointers.Add(new ULongPointer(&value));
  *listOfULongPointers[0].Value = 0x321UL;
}

Assert.Equal(0x321UL, value);

Keep in mind that you're already dealing with references when you have a reference type such as OP's MyClass. So in that case all you need is a List<MyClass>.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.