locked
Why does System.Drawing.Rectangle become ValueType? RRS feed

  • Question

  • Hi all,

    I have a managed C++ class library I use from a C# program. All of the functions that take or return Rectangle, RectangleF, or other structs now take or return ValueType.

    Why is this and how can I fix it?

    Tuesday, October 17, 2006 1:17 AM

Answers

  • Hmm, this seems to be a leak in the C++ compiler, it would have been nice if it would generate a warning, something like "not CLS-compliant".  The correct signatures for SetClipRect() are:
      void SetClipRect(System::Drawing::Rectangle rc);    // pass by value
      void SetClipRect(System::Drawing::Rectangle% rc); // pass by reference

    With Rectangle^ rc, the C# compiler boxes the argument and the C++ compiler casts the argument to a Rectangle.  Unfortunately, you are actually allowed to program this:
      SetClipRect(1);
    which generates an invalid cast exception on the C++ side at runtime.  The C++ compiler however has no problem type-checking the argument at compile time.

    Long story short: use the hat only with reference types.
    Wednesday, October 18, 2006 12:50 PM

All replies

  • Rectangle, RectangleF, etc are derived from ValueType however the parameters or return values from a method or property are determined by the class definition.  What do you mean they are now value types?  Can you post the code for the managed C++ class library and what you are seeing on the C# side?

    Michael Taylor - 10/17/06
    Tuesday, October 17, 2006 12:39 PM
  • The Rectangle and RectangleF types are simple struct declarations.  In the .NET CLR, structs are value types.  They get allocated on the stack instead of the managed heap, giving Java a nice kick in the pants.  Conversion to a reference type (or Object) is automatic through a process called 'boxing'.  That has a few nasty side-effects that every .NET programmer should know about.

    Getting to the point: what is your problem?

    Tuesday, October 17, 2006 9:39 PM
  • I have a managed C++ class that with a function like this:

    void SetClipRect(System::Drawing::Rectangle ^ rectangle);

    Using this from a C# program the function signature looks like this in metadata:

    void SetClipRect(System.ValueType rectangle);

    Why was the Rectangle object changed to a ValueType?

    If I change "System::Drawing::Rectangle ^ rectangle" to "System::Drawing::Rectangle rectangle" the signature is correct.

    Tuesday, October 17, 2006 9:56 PM
  • Hmm, this seems to be a leak in the C++ compiler, it would have been nice if it would generate a warning, something like "not CLS-compliant".  The correct signatures for SetClipRect() are:
      void SetClipRect(System::Drawing::Rectangle rc);    // pass by value
      void SetClipRect(System::Drawing::Rectangle% rc); // pass by reference

    With Rectangle^ rc, the C# compiler boxes the argument and the C++ compiler casts the argument to a Rectangle.  Unfortunately, you are actually allowed to program this:
      SetClipRect(1);
    which generates an invalid cast exception on the C++ side at runtime.  The C++ compiler however has no problem type-checking the argument at compile time.

    Long story short: use the hat only with reference types.
    Wednesday, October 18, 2006 12:50 PM