Error in .NET

Programs with the same structure behave differently in C# and in C++.

Event handlers of the class System.Windows.Forms.Form are polymorph in C# and non-polymorph in C++.

Example:

// Error.cs

// Two form classes: SecondForm is derived from FirstForm and it overrides the MouseDownHandler

using System.Windows.Forms;

public class FirstForm: Form

{

      public FirstForm()

      { // hang in MouseDown-handler:

            this.MouseDown += new MouseEventHandler(this.MouseDownHandler);

            }

      protected virtual void MouseDownHandler(object source, MouseEventArgs e)

      {

            MessageBox.Show("First Form", "", MessageBoxButtons.OK);

         }

}

 

public class SecondForm: FirstForm

{

      protected override void MouseDownHandler(object source, MouseEventArgs e)

      {

            MessageBox.Show("Second Form", "", MessageBoxButtons.OK);

      }

      public static void Main(string[] kzp)

      {

            System.Windows.Forms.Application.Run(new SecondForm());

           } 

}

Mouse click on the form produces the message “Second Form” (as expected).


The same program in C++:

// Error.cpp

#using <mscorlib.dll>

#using <System.DLL>

#using <System.Windows.Forms.DLL>

 

// First form class

using namespace System::Windows::Forms;

 

__gc class FirstForm: public System::Windows::Forms::Form

{

public:

      FirstForm();

protected:

      virtual void MouseDownHandler(Object* s, MouseEventArgs* e);

};

 

// First form methods

FirstForm::FirstForm()

{

      this -> MouseDown += new MouseEventHandler(this, MouseDownHandler);

}

void FirstForm::MouseDownHandler(Object* s, MouseEventArgs* e)

{

      MessageBox::Show("First Form", "", MessageBoxButtons::OK);

}

 

// Second form class

__gc class SecondForm: public FirstForm

{

protected:

      virtual void MouseDownHandler(Object* s, MouseEventArgs* e);

};

 

// First form method

void SecondForm::MouseDownHandler(Object* s, MouseEventArgs* e)

{

      MessageBox::Show("Second Form", "", MessageBoxButtons::OK);

}

 

// main starts SecondForm

void main()

{

      Application::Run(new SecondForm());

}

Mouse click on the form produces the message “First Form” (in contrary to the C# version).

 


The reason for the difference is:


Workaround: call another virtual method in the C++-handler – this one should be overwritten. MouseDownHandler does not have to be necessarily virtual:

// Workaround.cpp

#using <mscorlib.dll>

#using <System.DLL>

#using <System.Windows.Forms.DLL>

 

// First form class

using namespace System::Windows::Forms;

 

__gc class FirstForm: public System::Windows::Forms::Form

{

public:

      FirstForm();

protected:

      void MouseDownHandler(Object* s, MouseEventArgs* e); // not virtual anymore

      virtual void AnotherMethod(Object* s, MouseEventArgs* e); // virtual

};

 

// First form methods

FirstForm::FirstForm()

{

            this -> MouseDown += new MouseEventHandler(this, MouseDownHandler);

}

void FirstForm::MouseDownHandler(Object* s, MouseEventArgs* e)

{

      AnotherMethod(s, e); // call virtual method

}

void FirstForm::AnotherMethod(Object* s, MouseEventArgs* e)

{

      MessageBox::Show("First Form", "", MessageBoxButtons::OK); // event handler

}

 

// Second form class

__gc class SecondForm: public FirstForm

{

protected:

      virtual void AnotherMethod(Object* s, MouseEventArgs* e); // overwrite 

};

 

// First form method

void SecondForm::AnotherMethod(Object* s, MouseEventArgs* e)

{

      MessageBox::Show("Second Form", "", MessageBoxButtons::OK); // event handler

 

// main starts SecondForm

void main()

{

      Application::Run(new SecondForm());

}

 

Mouse click on the form produces the message “Second Form” (as expected, as in C#).


Sources:

Reply to