Can I add an implicit conversion for two classes which I don't directly control?
I'd like to be able to implicitly convert between two classes which are otherwise incompatible.
One of the classes is Microsoft.Xna.Framework.Vector3
, and the other is just a Vector
class used in an F# project. I'm writing a 3d game in C# with XNA, and -- although it's drawn in 3D, the gameplay takes place in only two dimensions (it's a birds-eye-view). The F# class takes care of the physics, using a 2D vector:
type Vector<'t when 't :> SuperUnit<'t>> =
| Cartesian of 't * 't
| Polar of 't * float
member this.magnitude =
match this with
| Cartesian(x, y) -> x.newValue(sqrt (x.units ** 2.0 + y.units ** 2.0))
| Polar(m, _) -> m.newValue(m.units)
member this.direction =
match this with
| Cartesian(x, y) -> tan(y.units / x.units)
| Polar(_, d) -> d
member this.x =
match this with
| Cartesian(x, _) -> x
| Polar(m, d) -> m.newValue(m.units * cos(d))
member this.y =
match this with
| Cartesian(_, y) -> y
| Polar(m, d) -> m.newValue(m.units * sin(d))
This vector class makes use of the unit system used by the physics project, which takes native F# units of measure and groups them together (units of Distance, Time, Mass, etc).
But XNA uses its own Vector3
class. I want to add an implicit conversion from the F# Vector
to the XNA Vector3
which takes care of which two dimensions the gameplay takes place in, which axis is "up", etc. It'd be simple, just Vector v -> new Vector3(v.x, v.y, 0)
or something.
I can't figure out how to do it though. I can't add an implicit conversion in F# because the type system (rightly) doesn't allow it. I can't add it to the Vector3 class because that is part of the XNA library. As far as I can tell I can't use an extension method:
class CsToFs
{
public static implicit operator Vector3(this Vector<Distance> v)
{
//...
}
}
Is an error on the this
keyword, and
class CsToFs
{
public static im开发者_StackOverflowplicit operator Vector3(Vector<Distance> v)
{
return new Vector3((float)v.x.units, (float)v.y.units, 0);
}
public static void test()
{
var v = Vector<Distance>.NewCartesian(Distance.Meters(0), Distance.Meters(0));
Vector3 a;
a = v;
}
}
is an error on a = v;
(cannot implicitly convert...).
Is there a way to do this without being able to put the cast in either of the classes? As a last resort I could open Microsoft.Xna.Framework
and do the conversion in F#, but that seems wrong to me -- the physics library shouldn't know or care what framework I'm using to write the game.
No, you can't. The implicit operator has to be defined as a member of one of the classes. However, you can define an extension method (your example didn't work as extension methods have to be in a public static class
).
public static class ConverterExtensions
{
public static Vector ToVector (this Vector3 input)
{
//convert
}
}
In C# you cannot. You could provide descendant types that have the extra conversions (provided the types aren't sealed); Or you could provide a generic wrapper class that somehow adds the conversion.
The convenience of all this depends on the way in which these wrappers/adaptations can be used with the original APIs.
On another note I see you are useing F# as well. IIRC F# is supposed to have some level of meta-programming ability (like many functional languages for .NET, such as Boo and Nemerle). It would not surprise me if that could be used here. Unfortunately my F is not sharp enough to help there
精彩评论