By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,200 Members | 1,568 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,200 IT Pros & Developers. It's quick & easy.

implicit upcast possible?

P: n/a
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(Point3D 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(Point3D pt) { _x = pt.X; _y = pt.Y; _z = pt.Z; }

public static implicit operator Vector3D(Point3D 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.
Dec 5 '07 #1
Share this Question
Share on Google+
8 Replies


P: n/a
On Wed, 05 Dec 2007 14:38:54 -0800, jonpb <no****@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
Dec 5 '07 #2

P: n/a
jonpb <no****@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 - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
Dec 5 '07 #3

P: n/a

"jonpb" <no****@nospam.comwrote in message
news:uD****************@TK2MSFTNGP05.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(Point3D 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(Point3D pt) { _x = pt.X; _y = pt.Y; _z = pt.Z; }

public static implicit operator Vector3D(Point3D 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.

Dec 5 '07 #4

P: n/a

"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
On Wed, 05 Dec 2007 14:38:54 -0800, jonpb <no****@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(Point3D) constructor is an option however.
>
Pete

Dec 5 '07 #5

P: n/a
On Wed, 05 Dec 2007 15:13:50 -0800, Ben Voigt [C++ MVP]
<rb*@nospam.nospamwrote:
>[...]
* 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
Dec 5 '07 #6

P: n/a
Ben Voigt [C++ MVP] wrote:
"jonpb" <no****@nospam.comwrote in message
>>
public static implicit operator Vector3D(Point3D 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.
Dec 6 '07 #7

P: n/a
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.
Dec 6 '07 #8

P: n/a
jonpb <no****@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.InvalidCastException 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 - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
Dec 6 '07 #9

This discussion thread is closed

Replies have been disabled for this discussion.