views:

444

answers:

2

I am trying to create a generic list of references to PointF objects. (No, I am not looking to create a generic list of PointF objects.) However, the following line fails to compile:

Generic::List<PointF^> ^pointList; // Generates error C3225

On the other hand, creating an array of PointF references works without a problem as follows:

array<PointF^> ^points = gcnew array<PointF^>;

Here is a sample program:

using namespace System; using namespace System::Drawing; namespace Generic = System::Collections::Generic;

int main(array ^args) {

array ^points = gcnew array{ nullptr, PointF(0.0f, 0.0f), PointF(1.0f, 0.0f), nullptr };

Generic::List ^pointList; Console::WriteLine(L"Hello World"); return 0; }

How do I create a generic list of PointF references? In other words, how do I create a generic list of boxed PointFs?

Update: As an alternative, I could use Nullable<PointF> but that still does not explain why array<PointF^> compiles silently whereas Generic::List<PointF^> does not.

A: 

PointF is not a class, it's a structure. You can't have references to a structure without boxing it inside an object.

You can either have a list of Object references and unbox the reference to PointF whenever you use it, or a list of a custom class that encapsulates a PointF value.

With implicit conversions to and from a PointF value you can make the boxing and unboxing transparent. I'm not sure how you write it in C++, but in C# it would look like this:

public class PointFObject {

   // encapsulated PointF structure
   private PointF _value;

   // constructor
   public PointFObject(PointF value) {
      _value = value;
   }

   // implicit conversion to a PointF value
   public static implicit operator PointF(PointFObject obj) {
      return obj._value;
   }

   // implicit conversion from a PointF value
   public static implicit operator PointFObject(PointF value) {
      return new PointFObject(value);
   }

}

Now you can create a list of PointFObject and access them as a list of PointF values:

List<PointFObject> pointList = new List<PointFObject>();
pointList.Add(new PointF(0f, 0f));
PointF p = pointList[0];
Guffa
Why is it then that array<PointF^> compiles without problems? The compiler automatically handles boxing/unboxing in this case. Why won't it work in the case of a generic list?
Vulcan Eager
+2  A: 

It is a limit of the .Net generic, which only takes a CLI complient type such as a value type or a reference to a reference type. It does not take C++/CLI-specific types like stack semantics for ref types (which compiles into deterministic finalization) or, in you case, a reference to a boxed value type.

Array is native to CLI and does not have this restriction.

Sheng Jiang 蒋晟