开发者

Can I add an implicit conversion for two classes which I don't directly control?

开发者 https://www.devze.com 2023-02-22 04:27 出处:网络
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

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

0

精彩评论

暂无评论...
验证码 换一张
取 消