implicit upcast possible?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • jonpb

    #1

    implicit upcast possible?

    Hi, Is it possible to define a implicit operator from base to derived
    types in C#?
    I have a Point class and would like to derive a Vector class from it and
    add a couple new vector related functions, like Normalize(). The problem
    is Vector cannot use any of the Point operator overloads with a compile
    time error that there is no implicit conversion from Point to Vector. I
    tried adding an implicit operator to Vector:

    public static implicit operator Vector3D(Point3 D a)
    { return new Vector3D(pt); }

    But that doesn't compile either resulting error CS0553. Here is some
    relevant code snips:

    public class Point3D
    {
    protected double _x, _y, _z;

    public static Point3D operator *(Point3D a, double b)
    {
    return new Point3D(a.X * b, a.Y * b, a.Z * b);
    }
    }

    public class Vector3D : Point3D
    {
    public Vector3D(Point3 D pt) { _x = pt.X; _y = pt.Y; _z = pt.Z; }

    public static implicit operator Vector3D(Point3 D a)
    { return new Vector3D(pt); }
    }

    If it allows and explicit upcast conversion, I don't understand why it
    would not allow me to define an implicit operator, being the author of
    the classes I know that it is safe to upcast implicitly.

    Thanks.
  • Peter Duniho

    #2
    Re: implicit upcast possible?

    On Wed, 05 Dec 2007 14:38:54 -0800, jonpb <nospam@nospam. comwrote:
    [...]
    If it allows and explicit upcast conversion, I don't understand why it
    would not allow me to define an implicit operator, being the author of
    the classes I know that it is safe to upcast implicitly.
    I'm sure someone more knowledgeable will provide a detailed answer. But a
    couple of thoughts from the peanut gallery:

    * How is an implicit upcast supposed to work, especially when defined
    in the derived class? All the compiler knows is that you've got a
    Point3D, and the implicit cast defined is not in that class. Never mind
    the question of what the behavior should be given that multiple derived
    types could exist and would not necessarily be known at the time the
    upcasting code was compiled.

    * As far as the specific problem goes, can't you just define a new
    operator* in Vector3D that just uses the base class version, explicitly
    casting back up to Vector3D for the result?

    Pete

    Comment

    • Jon Skeet [C# MVP]

      #3
      Re: implicit upcast possible?

      jonpb <nospam@nospam. comwrote:
      Hi, Is it possible to define a implicit operator from base to derived
      types in C#?
      No. From the spec, section 10.10.3 (unified C#3 spec)

      <quote>
      For a given source type S and target type T, if S or T are nullable
      types, let S0 and T0 refer to their underlying types, otherwise S0 and
      T0 are equal to S and T respectively. A class or struct is permitted to
      declare a conversion from a source type S to a target type T only if
      all of the following are true:
      " S0 and T0 are different types.
      " Either S0 or T0 is the class or struct type in which the operator
      declaration takes place.
      " Neither S0 nor T0 is an interface-type.
      " Excluding user-defined conversions, a conversion does not exist
      from S to T or from T to S.
      </quote>

      Note the last point.

      --
      Jon Skeet - <skeet@pobox.co m>
      http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
      World class .NET training in the UK: http://iterativetraining.co.uk

      Comment

      • Ben Voigt [C++ MVP]

        #4
        Re: implicit upcast possible?


        "jonpb" <nospam@nospam. comwrote in message
        news:uDWPg%234N IHA.1208@TK2MSF TNGP05.phx.gbl. ..
        Hi, Is it possible to define a implicit operator from base to derived
        types in C#?
        I have a Point class and would like to derive a Vector class from it and
        add a couple new vector related functions, like Normalize(). The problem
        is Vector cannot use any of the Point operator overloads with a compile
        time error that there is no implicit conversion from Point to Vector. I
        tried adding an implicit operator to Vector:
        >
        public static implicit operator Vector3D(Point3 D a)
        { return new Vector3D(pt); }
        >
        But that doesn't compile either resulting error CS0553. Here is some
        relevant code snips:
        >
        public class Point3D
        {
        protected double _x, _y, _z;
        >
        public static Point3D operator *(Point3D a, double b)
        {
        return new Point3D(a.X * b, a.Y * b, a.Z * b);
        }
        }
        >
        public class Vector3D : Point3D
        {
        public Vector3D(Point3 D pt) { _x = pt.X; _y = pt.Y; _z = pt.Z; }
        >
        public static implicit operator Vector3D(Point3 D a)
        { return new Vector3D(pt); }
        }
        >
        If it allows and explicit upcast conversion, I don't understand why it
        would not allow me to define an implicit operator, being the author of the
        classes I know that it is safe to upcast implicitly.
        That's a downcast. MSDN gives the reason:

        It is not possible to redefine a pre-defined conversion. Thus, conversion
        operators are not allowed to convert from or to object because implicit and
        explicit conversions already exist between object and all other types.
        Likewise, neither the source nor the target types of a conversion can be a
        base type of the other, since a conversion would then already exist.

        http://msdn2.microsoft.com/en-us/library/aa664464.aspx

        The existing conversion is a dynamic type check... which will fail.

        Overload the functions as Peter suggests.
        >
        Thanks.

        Comment

        • Ben Voigt [C++ MVP]

          #5
          Re: implicit upcast possible?


          "Peter Duniho" <NpOeStPeAdM@nn owslpianmk.comw rote in message
          news:op.t2vwipz 28jd0ej@petes-computer.local. ..
          On Wed, 05 Dec 2007 14:38:54 -0800, jonpb <nospam@nospam. comwrote:
          >
          >[...]
          >If it allows and explicit upcast conversion, I don't understand why it
          >would not allow me to define an implicit operator, being the author of
          >the classes I know that it is safe to upcast implicitly.
          >
          I'm sure someone more knowledgeable will provide a detailed answer. But a
          couple of thoughts from the peanut gallery:
          >
          * How is an implicit upcast supposed to work, especially when defined
          in the derived class? All the compiler knows is that you've got a
          Point3D, and the implicit cast defined is not in that class. Never mind
          the question of what the behavior should be given that multiple derived
          types could exist and would not necessarily be known at the time the
          upcasting code was compiled.
          >
          * As far as the specific problem goes, can't you just define a new
          operator* in Vector3D that just uses the base class version, explicitly
          casting back up to Vector3D for the result?
          No, the explicit cast (downcast) will do a dynamic type check. Since the
          runtime type is not Vector3D, it will fail with an exception.

          Calling the Vector3D(Point3 D) constructor is an option however.
          >
          Pete

          Comment

          • Peter Duniho

            #6
            Re: implicit upcast possible?

            On Wed, 05 Dec 2007 15:13:50 -0800, Ben Voigt [C++ MVP]
            <rbv@nospam.nos pamwrote:
            >[...]
            > * As far as the specific problem goes, can't you just define a new
            >operator* in Vector3D that just uses the base class version, explicitly
            >casting back up to Vector3D for the result?
            >
            No, the explicit cast (downcast) will do a dynamic type check. Since the
            runtime type is not Vector3D, it will fail with an exception.
            Ah, right. I should have looked more closely at the operator definition
            itself.

            But as you say, using the constructor is an alternative to casting that
            would actually work.

            Pete

            Comment

            • jonpb

              #7
              Re: implicit upcast possible?

              Ben Voigt [C++ MVP] wrote:
              "jonpb" <nospam@nospam. comwrote in message
              >>
              >public static implicit operator Vector3D(Point3 D a)
              >{ return new Vector3D(pt); }
              >>
              That's a downcast. MSDN gives the reason:
              No, it's an upcast going from base (Point3D) to derived (Vector3D).
              On that point, the error message that VS2005 gives you is wrong also, as
              it says, as you said, that it is downcast and is not required.
              http://msdn2.microsoft.com/en-us/library/aa664464.aspx
              >
              The existing conversion is a dynamic type check... which will fail.
              Ok, I must have eaten a bowl full of stupid today, because I really
              don't get this. The spec is saying that a conversion "already exists" to
              and from base and derived classes, and yet, in the case of base to
              derived (upcast), the compiler can't find the implicit one and the
              explicit one results in a runtime error.
              >
              Overload the functions as Peter suggests.
              The whole point in deriving was not to have to do that. oh, well.


              Comment

              • jonpb

                #8
                Re: implicit upcast possible?

                jonpb wrote:
                Ok, I must have eaten a bowl full of stupid today, because I really
                don't get this. The spec is saying that a conversion "already exists" to
                and from base and derived classes, and yet, in the case of base to
                derived (upcast), the compiler can't find the implicit one and the
                explicit one results in a runtime error.
                Sorry I should have continued that thought:

                And on top of that, It won't let you define an implicit cast that you
                know will be safe, because it thinks it is already defined, even though
                it can't find it!

                For what it's worth, I don't think upcasting implicitly or explicitly
                should be allowed unless specifically defined by the author of the
                objects. But, I do feel strongly that the ability to define these casts
                would be very helpful.

                Comment

                • Jon Skeet [C# MVP]

                  #9
                  Re: implicit upcast possible?

                  jonpb <nospam@nospam. comwrote:
                  That's a downcast. MSDN gives the reason:
                  No, it's an upcast going from base (Point3D) to derived (Vector3D).
                  On that point, the error message that VS2005 gives you is wrong also, as
                  it says, as you said, that it is downcast and is not required.
                  No - base to derived = downcast. Derived to base = upcast.
                  http://msdn2.microsoft.com/en-us/library/aa664464.aspx

                  The existing conversion is a dynamic type check... which will fail.
                  Ok, I must have eaten a bowl full of stupid today, because I really
                  don't get this. The spec is saying that a conversion "already exists" to
                  and from base and derived classes, and yet, in the case of base to
                  derived (upcast), the compiler can't find the implicit one and the
                  explicit one results in a runtime error.
                  There's an explicit conversion from an expression of type Base to
                  Derived - but it may fail at execution time. There's no implicit
                  conversion precisely because it may fail at execution time.

                  From the spec (section 6.2.4, unified C# 3 spec):

                  <quote>
                  The explicit reference conversions are:

                  ....

                  " From any class-type S to any class-type T, provided S is a base
                  class of T.

                  ....
                  The explicit reference conversions are those conversions between
                  reference-types that require run-time checks to ensure they are
                  correct.

                  For an explicit reference conversion to succeed at run-time, the value
                  of the source operand must be null, or the actual type of the object
                  referenced by the source operand must be a type that can be converted
                  to the destination type by an implicit reference conversion (ยง6.1.6).
                  If an explicit reference conversion fails, a
                  System.InvalidC astException is thrown.
                  </quote>

                  In other words, you can do:

                  Base b = new Derived();
                  Derived d = (Derived) b; // Works

                  But you can't do:

                  Base b = new Base();
                  Derived d = (Derived) b; // Fails

                  because in the latter case the object isn't *actually* an instance of
                  Derived.

                  --
                  Jon Skeet - <skeet@pobox.co m>
                  http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
                  World class .NET training in the UK: http://iterativetraining.co.uk

                  Comment

                  Working...