Operator overloading question

Operator overloading question

Post by Rob Hooke » Sun, 28 Jan 2001 00:39:25



Hi all,

We'd like your thoughts on the apparent broken polymorphism in C# when
dealing with operator overloading.

UnitsBase implements operator+, and we'd like derived classes to pick up the
default implementation most of the time, and override it some of the time.
We'd like to have other functions etc that deal only with the baseclass type
and perform math operations on them using the +,-,* operators etc.

Seems like it should be easy (it was in C++ anyway)

We seem to have a couple of problems (you should be able to paste this code
into a .cs and compile if you are keen!)

1] Forced to do unneeded casting

namespace TestOps
{
  using System;

//base class
  public abstract class UnitsBase
  {
    public double m_dVal;
    public UnitsBase() {m_dVal = 0.0F;}
    public UnitsBase(double f) {m_dVal = f;}

    public static UnitsBase operator+(UnitsBase a, UnitsBase b)
    {
//The next line wont work, as UnitsBase is abstract
//      return new UnitsBase( a.m_dVal + b.m_dVal );
//
// So we do this instead:
//
// This creates a new of type Derived (Distance in this case)
       UnitsBase unit = (Unit) Activator.CreateInstance(a.GetType());
       unit.m_dVal = a.m_dVal + b.m_dVal;
// This should return it
       return unit;
    }
  }

  public class Distance : UnitsBase
  {
    public Distance(double f)
   {m_dVal = f;}
  }

  // Main
  public class OperatorsMainClass
  {
    public static void Main (string[] args)
   {
    Distance dist1 = new Distance(8);
    Distance dist2 = new Distance(16);

// !!!!!!!!!!!!!!!
// This uses the operator+ above, but requires that I cast (dist1 +dist2)
into type Distance, even though
// that is what is being returned by operator+
// !!!!!!!!!!!!!!!
//  Distance dist3 = dist1 + dist2;
  Distance dist3 = (Distance) dist1 + dist2;
    }
  }

Quote:}

2] Polymorphism seems broken, or am I doing some wrong?

Because the operator+ must be static, it cannot be virtual, so if we need do
this:

  public abstract class UnitsBase
  {
    public static UnitsBase operator+(UnitsBase a, UnitsBase b)
    {
       UnitsBase unit = (Unit) Activator.CreateInstance(a.GetType());
       unit.m_dVal = a.m_dVal + b.m_dVal;
// This should return it
       return unit;    }
  }

// Each derived class actually implements operator+
//
public class Distance : UnitsBase
  {
    public static Distance operator+(Distance a, Distance b)
    {
      return new Distance(a.m_dVal + b.m_dVal );
    }
  }

So far so good, but if I do this:

Distance dist1 = new Distance(8);
Distance dist2 = new Distance(16);
Func(dist1,dist2); // These are Distances passed in

where Func is,

public static void Func(UnitsBase a, UnitsBase b)
{
UnitsBase c = a+b; // Always uses UnitsBase operator+ even though both a and
                            // b are actually of type Distance

Quote:}

I think all of this stems from the fact that the operators must be static,
so can anyone give me a hint as to how we can have operators in a baseclass,
and sometimes override them in derived classes, and have functions that deal
with the basetype only and perform math operations on them...?
 
 
 

Operator overloading question

Post by MSFT » Sun, 28 Jan 2001 01:15:49


You're trying to get polymorphism for operators, and, as you note, they
don't support polymorphism.

You therefore need to use something that does support polymorphism. You'll
need to write virtual methods that do what you want, and call them from the
operators. See inline.


Quote:> Hi all,

> We'd like your thoughts on the apparent broken polymorphism in C# when
> dealing with operator overloading.

> UnitsBase implements operator+, and we'd like derived classes to pick up
the
> default implementation most of the time, and override it some of the time.
> We'd like to have other functions etc that deal only with the baseclass
type
> and perform math operations on them using the +,-,* operators etc.

> Seems like it should be easy (it was in C++ anyway)

> We seem to have a couple of problems (you should be able to paste this
code
> into a .cs and compile if you are keen!)

> 1] Forced to do unneeded casting

> namespace TestOps
> {
>   using System;

> //base class
>   public abstract class UnitsBase
>   {
>     public double m_dVal;
>     public UnitsBase() {m_dVal = 0.0F;}
>     public UnitsBase(double f) {m_dVal = f;}

>     public static UnitsBase operator+(UnitsBase a, UnitsBase b)
>     {

            if (a.GetType() != b.GetType())
                throw new InvalidArgumentException("+ operators are of
different types");

            return(a.Add(b));

- Show quoted text -

Quote:> //The next line wont work, as UnitsBase is abstract
> //      return new UnitsBase( a.m_dVal + b.m_dVal );
> //
> // So we do this instead:
> //
> // This creates a new of type Derived (Distance in this case)
>        UnitsBase unit = (Unit) Activator.CreateInstance(a.GetType());
>        unit.m_dVal = a.m_dVal + b.m_dVal;
> // This should return it
>        return unit;
>     }
>   }

>   public class Distance : UnitsBase
>   {
>     public Distance(double f)
>    {m_dVal = f;}
>   }

>   // Main
>   public class OperatorsMainClass
>   {
>     public static void Main (string[] args)
>    {
>     Distance dist1 = new Distance(8);
>     Distance dist2 = new Distance(16);

> // !!!!!!!!!!!!!!!
> // This uses the operator+ above, but requires that I cast (dist1 +dist2)
> into type Distance, even though
> // that is what is being returned by operator+
> // !!!!!!!!!!!!!!!
> //  Distance dist3 = dist1 + dist2;
>   Distance dist3 = (Distance) dist1 + dist2;
>     }
>   }
> }

> 2] Polymorphism seems broken, or am I doing some wrong?

> Because the operator+ must be static, it cannot be virtual, so if we need
do
> this:

>   public abstract class UnitsBase
>   {
>     public static UnitsBase operator+(UnitsBase a, UnitsBase b)
>     {
>        UnitsBase unit = (Unit) Activator.CreateInstance(a.GetType());
>        unit.m_dVal = a.m_dVal + b.m_dVal;
> // This should return it
>        return unit;    }
>   }

> // Each derived class actually implements operator+
> //
> public class Distance : UnitsBase
>   {
>     public static Distance operator+(Distance a, Distance b)
>     {
>       return new Distance(a.m_dVal + b.m_dVal );
>     }
>   }

> So far so good, but if I do this:

> Distance dist1 = new Distance(8);
> Distance dist2 = new Distance(16);
> Func(dist1,dist2); // These are Distances passed in

> where Func is,

> public static void Func(UnitsBase a, UnitsBase b)
> {
> UnitsBase c = a+b; // Always uses UnitsBase operator+ even though both a
and
>                             // b are actually of type Distance
> }

> I think all of this stems from the fact that the operators must be static,
> so can anyone give me a hint as to how we can have operators in a
baseclass,
> and sometimes override them in derived classes, and have functions that
deal
> with the basetype only and perform math operations on them...?

As noted, you'll need a virtual Add() (and virtuals for all other operations
in your base class as well), and then override them if desired in your
derived classes. You'll need to be careful that all derived classes
implement these correctly, and that you don't allow operations on two
different types.

If you want your class to be consumed by all .NET languages, you'll need to
do this anyway, since some languages don't support using operator
overloading.

 
 
 

Operator overloading question

Post by Rob Hooke » Tue, 30 Jan 2001 15:34:33


Previously we had actually attempted your suggestion as a possible solution,
but, while it solves the polymorphism\operators issue, it still leaves us
with the casting issue. i.e.

// Base, with operator and "virtual Add" which does the work
public abstract class UnitsBase
{
   public static UnitsBase operator+(UnitsBase a, UnitsBase b)
   {
     return(a.Add(b));
   }
  public virtual UnitsBase Add(UnitsBase b)
 {
    // Do the default add
 }

Quote:}

// Base which possibly overrides Add
public class Distance : UnitsBase
{
  // Override the Add if needed
  public override UnitsBase Add(UnitsBase b)
  {
     // Do the add
  }

Quote:}

Distance dist1 = new Distance(8);
Distance dist2 = new Distance(16);

// This line fails to compile, "Cannot implicitly convert type "UnitsBase"
to type "Distance" "
Distance dist3 = dist1 + dist2;
// Needs to look like this
//Distance dist3 = (Distance)(dist1 + dist2);

When I add something like this to Distance, to handle the conversion:

public static implicit operator UnitsBase(Distance d)
{
   // Do a cast

Quote:}

The compile complains that I have provided a "user-defined conversion
to\from baseclass" and fails to compile....

We'd like to avoid having to sprinkle code with all sorts of seemingly
pointless casts... any idea's?
(We even toyed with Managed C++ for this stuff, but the compiler wont let us
do operators at ALL in Managed C++!!)

Robert.



> You're trying to get polymorphism for operators, and, as you note, they
> don't support polymorphism.

> You therefore need to use something that does support polymorphism. You'll
> need to write virtual methods that do what you want, and call them from
the
> operators. See inline.



> > Hi all,

> > We'd like your thoughts on the apparent broken polymorphism in C# when
> > dealing with operator overloading.

> > UnitsBase implements operator+, and we'd like derived classes to pick up
> the
> > default implementation most of the time, and override it some of the
time.
> > We'd like to have other functions etc that deal only with the baseclass
> type
> > and perform math operations on them using the +,-,* operators etc.

> > Seems like it should be easy (it was in C++ anyway)

> > We seem to have a couple of problems (you should be able to paste this
> code
> > into a .cs and compile if you are keen!)

> > 1] Forced to do unneeded casting

> > namespace TestOps
> > {
> >   using System;

> > //base class
> >   public abstract class UnitsBase
> >   {
> >     public double m_dVal;
> >     public UnitsBase() {m_dVal = 0.0F;}
> >     public UnitsBase(double f) {m_dVal = f;}

> >     public static UnitsBase operator+(UnitsBase a, UnitsBase b)
> >     {

>             if (a.GetType() != b.GetType())
>                 throw new InvalidArgumentException("+ operators are of
> different types");

>             return(a.Add(b));

> > //The next line wont work, as UnitsBase is abstract
> > //      return new UnitsBase( a.m_dVal + b.m_dVal );
> > //
> > // So we do this instead:
> > //
> > // This creates a new of type Derived (Distance in this case)
> >        UnitsBase unit = (Unit) Activator.CreateInstance(a.GetType());
> >        unit.m_dVal = a.m_dVal + b.m_dVal;
> > // This should return it
> >        return unit;
> >     }
> >   }

> >   public class Distance : UnitsBase
> >   {
> >     public Distance(double f)
> >    {m_dVal = f;}
> >   }

> >   // Main
> >   public class OperatorsMainClass
> >   {
> >     public static void Main (string[] args)
> >    {
> >     Distance dist1 = new Distance(8);
> >     Distance dist2 = new Distance(16);

> > // !!!!!!!!!!!!!!!
> > // This uses the operator+ above, but requires that I cast (dist1
+dist2)
> > into type Distance, even though
> > // that is what is being returned by operator+
> > // !!!!!!!!!!!!!!!
> > //  Distance dist3 = dist1 + dist2;
> >   Distance dist3 = (Distance) dist1 + dist2;
> >     }
> >   }
> > }

> > 2] Polymorphism seems broken, or am I doing some wrong?

> > Because the operator+ must be static, it cannot be virtual, so if we
need
> do
> > this:

> >   public abstract class UnitsBase
> >   {
> >     public static UnitsBase operator+(UnitsBase a, UnitsBase b)
> >     {
> >        UnitsBase unit = (Unit) Activator.CreateInstance(a.GetType());
> >        unit.m_dVal = a.m_dVal + b.m_dVal;
> > // This should return it
> >        return unit;    }
> >   }

> > // Each derived class actually implements operator+
> > //
> > public class Distance : UnitsBase
> >   {
> >     public static Distance operator+(Distance a, Distance b)
> >     {
> >       return new Distance(a.m_dVal + b.m_dVal );
> >     }
> >   }

> > So far so good, but if I do this:

> > Distance dist1 = new Distance(8);
> > Distance dist2 = new Distance(16);
> > Func(dist1,dist2); // These are Distances passed in

> > where Func is,

> > public static void Func(UnitsBase a, UnitsBase b)
> > {
> > UnitsBase c = a+b; // Always uses UnitsBase operator+ even though both a
> and
> >                             // b are actually of type Distance
> > }

> > I think all of this stems from the fact that the operators must be
static,
> > so can anyone give me a hint as to how we can have operators in a
> baseclass,
> > and sometimes override them in derived classes, and have functions that
> deal
> > with the basetype only and perform math operations on them...?

> As noted, you'll need a virtual Add() (and virtuals for all other
operations
> in your base class as well), and then override them if desired in your
> derived classes. You'll need to be careful that all derived classes
> implement these correctly, and that you don't allow operations on two
> different types.

> If you want your class to be consumed by all .NET languages, you'll need
to
> do this anyway, since some languages don't support using operator
> overloading.

 
 
 

Operator overloading question

Post by MSFT » Wed, 31 Jan 2001 08:03:28


You are correct. The only way around it is to define operator+ in the
derived class.


> Previously we had actually attempted your suggestion as a possible
solution,
> but, while it solves the polymorphism\operators issue, it still leaves us
> with the casting issue. i.e.

> // Base, with operator and "virtual Add" which does the work
> public abstract class UnitsBase
> {
>    public static UnitsBase operator+(UnitsBase a, UnitsBase b)
>    {
>      return(a.Add(b));
>    }
>   public virtual UnitsBase Add(UnitsBase b)
>  {
>     // Do the default add
>  }
> }

> // Base which possibly overrides Add
> public class Distance : UnitsBase
> {
>   // Override the Add if needed
>   public override UnitsBase Add(UnitsBase b)
>   {
>      // Do the add
>   }
> }

> Distance dist1 = new Distance(8);
> Distance dist2 = new Distance(16);

> // This line fails to compile, "Cannot implicitly convert type "UnitsBase"
> to type "Distance" "
> Distance dist3 = dist1 + dist2;
> // Needs to look like this
> //Distance dist3 = (Distance)(dist1 + dist2);

> When I add something like this to Distance, to handle the conversion:

> public static implicit operator UnitsBase(Distance d)
> {
>    // Do a cast
> }

> The compile complains that I have provided a "user-defined conversion
> to\from baseclass" and fails to compile....

> We'd like to avoid having to sprinkle code with all sorts of seemingly
> pointless casts... any idea's?
> (We even toyed with Managed C++ for this stuff, but the compiler wont let
us
> do operators at ALL in Managed C++!!)

> Robert.



> > You're trying to get polymorphism for operators, and, as you note, they
> > don't support polymorphism.

> > You therefore need to use something that does support polymorphism.
You'll
> > need to write virtual methods that do what you want, and call them from
> the
> > operators. See inline.



> > > Hi all,

> > > We'd like your thoughts on the apparent broken polymorphism in C# when
> > > dealing with operator overloading.

> > > UnitsBase implements operator+, and we'd like derived classes to pick
up
> > the
> > > default implementation most of the time, and override it some of the
> time.
> > > We'd like to have other functions etc that deal only with the
baseclass
> > type
> > > and perform math operations on them using the +,-,* operators etc.

> > > Seems like it should be easy (it was in C++ anyway)

> > > We seem to have a couple of problems (you should be able to paste this
> > code
> > > into a .cs and compile if you are keen!)

> > > 1] Forced to do unneeded casting

> > > namespace TestOps
> > > {
> > >   using System;

> > > //base class
> > >   public abstract class UnitsBase
> > >   {
> > >     public double m_dVal;
> > >     public UnitsBase() {m_dVal = 0.0F;}
> > >     public UnitsBase(double f) {m_dVal = f;}

> > >     public static UnitsBase operator+(UnitsBase a, UnitsBase b)
> > >     {

> >             if (a.GetType() != b.GetType())
> >                 throw new InvalidArgumentException("+ operators are of
> > different types");

> >             return(a.Add(b));

> > > //The next line wont work, as UnitsBase is abstract
> > > //      return new UnitsBase( a.m_dVal + b.m_dVal );
> > > //
> > > // So we do this instead:
> > > //
> > > // This creates a new of type Derived (Distance in this case)
> > >        UnitsBase unit = (Unit) Activator.CreateInstance(a.GetType());
> > >        unit.m_dVal = a.m_dVal + b.m_dVal;
> > > // This should return it
> > >        return unit;
> > >     }
> > >   }

> > >   public class Distance : UnitsBase
> > >   {
> > >     public Distance(double f)
> > >    {m_dVal = f;}
> > >   }

> > >   // Main
> > >   public class OperatorsMainClass
> > >   {
> > >     public static void Main (string[] args)
> > >    {
> > >     Distance dist1 = new Distance(8);
> > >     Distance dist2 = new Distance(16);

> > > // !!!!!!!!!!!!!!!
> > > // This uses the operator+ above, but requires that I cast (dist1
> +dist2)
> > > into type Distance, even though
> > > // that is what is being returned by operator+
> > > // !!!!!!!!!!!!!!!
> > > //  Distance dist3 = dist1 + dist2;
> > >   Distance dist3 = (Distance) dist1 + dist2;
> > >     }
> > >   }
> > > }

> > > 2] Polymorphism seems broken, or am I doing some wrong?

> > > Because the operator+ must be static, it cannot be virtual, so if we
> need
> > do
> > > this:

> > >   public abstract class UnitsBase
> > >   {
> > >     public static UnitsBase operator+(UnitsBase a, UnitsBase b)
> > >     {
> > >        UnitsBase unit = (Unit) Activator.CreateInstance(a.GetType());
> > >        unit.m_dVal = a.m_dVal + b.m_dVal;
> > > // This should return it
> > >        return unit;    }
> > >   }

> > > // Each derived class actually implements operator+
> > > //
> > > public class Distance : UnitsBase
> > >   {
> > >     public static Distance operator+(Distance a, Distance b)
> > >     {
> > >       return new Distance(a.m_dVal + b.m_dVal );
> > >     }
> > >   }

> > > So far so good, but if I do this:

> > > Distance dist1 = new Distance(8);
> > > Distance dist2 = new Distance(16);
> > > Func(dist1,dist2); // These are Distances passed in

> > > where Func is,

> > > public static void Func(UnitsBase a, UnitsBase b)
> > > {
> > > UnitsBase c = a+b; // Always uses UnitsBase operator+ even though both
a
> > and
> > >                             // b are actually of type Distance
> > > }

> > > I think all of this stems from the fact that the operators must be
> static,
> > > so can anyone give me a hint as to how we can have operators in a
> > baseclass,
> > > and sometimes override them in derived classes, and have functions
that
> > deal
> > > with the basetype only and perform math operations on them...?

> > As noted, you'll need a virtual Add() (and virtuals for all other
> operations
> > in your base class as well), and then override them if desired in your
> > derived classes. You'll need to be careful that all derived classes
> > implement these correctly, and that you don't allow operations on two
> > different types.

> > If you want your class to be consumed by all .NET languages, you'll need
> to
> > do this anyway, since some languages don't support using operator
> > overloading.

 
 
 

1. Calling overloaded assignment operator written in MC++ from C#

I've got a managed class written in C++ (MC++).  I'm attempting to overload
operators such as assignment.  When I try to use the overloaded assignment
operator from my C# code, I get an error stating "Cannot implicitly convert
type 'int' to 'MyMCClass'".  Although, I can use the long form (i.e.
op_Assign) with no problems.  Any ideas?  The basic code structure I have
created is below.

public __gc class MyMCClass

{

public:

MyMCClass();

~MyMCClass();

static MyMCClass& op_Assign(MyMCClass& value, UInt32 int32);

////C# client code

MyMCClass mc = new MyMCClass();
mc = 120; //ERROR!! "Cannot implicitly convert type 'int' to 'MyMCClass'"
mc.op_Assign(mc, 120); //works fine!

Thanks,

Tim Rogers

2. Measures of Complexity

3. Operator overloading equivalent in Vb.net

4. ATM fonts on a DOS operating system

5. Operator Overloading and Visual Basic .NET

6. Remove frame and load content from a central file

7. How to overload operator->

8. shutdown problem Asus A1000 with OS Windows XP

9. source browser and overloaded operators

10. Setting link order to overload global operator new

11. VB.NET Operator overloading Enums?

12. Operator overload for Generics problem

13. Overloading of new[] operator