Могу ли я добавить неявное преобразование для двух классов, которые я не контролирую напрямую? - PullRequest
16 голосов
/ 03 апреля 2011

Я бы хотел иметь возможность неявного преобразования между двумя классами, которые в противном случае несовместимы.

Один из классов - Microsoft.Xna.Framework.Vector3, а другой - просто Vector класс, используемый в F #проект.Я пишу 3D-игру на C # с XNA, и - хотя она и нарисована в 3D, игровой процесс разворачивается только в двух измерениях (это с высоты птичьего полета).Класс F # заботится о физике, используя двумерный вектор:

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))

Этот векторный класс использует систему единиц, используемую в физическом проекте, которая берет собственные единицы измерения F # и группирует их вместе (единицы расстояния, времени, массы и т. д.).

Но XNA использует свой собственный класс Vector3.Я хочу добавить неявное преобразование из F # Vector в XNA Vector3, которое заботится о , в котором два измерения игрового процесса, какая ось "вверх" и т. Д.будь простым, просто Vector v -> new Vector3(v.x, v.y, 0) или что-то.

Хотя я не могу понять, как это сделать.Я не могу добавить неявное преобразование в F #, потому что система типов (правильно) не позволяет этого.Я не могу добавить его в класс Vector3, потому что это часть библиотеки XNA.Насколько я могу судить, я не могу использовать метод расширения:

class CsToFs
{
    public static implicit operator Vector3(this Vector<Distance> v)
    {
        //...
    }
}

Ошибка в ключевом слове this, а

class CsToFs
{
    public static implicit 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;
    }
}

- ошибка a = v; (не может неявно преобразовать ...).

Есть ли способ сделать это, не имея возможности использовать приведение в любом из классов?В крайнем случае я мог бы open Microsoft.Xna.Framework и выполнить преобразование в F #, но мне это кажется неправильным - физическая библиотека не должна знать или заботиться о том, какую среду я использую для написания игры.

Ответы [ 2 ]

15 голосов
/ 03 апреля 2011

Нет, вы не можете.Неявный оператор должен быть определен как член одного из классов.Однако вы можете определить метод расширения (ваш пример не работал, так как методы расширения должны быть в public static class).

public static class ConverterExtensions
{
    public static Vector ToVector (this Vector3 input)
    {
      //convert
    }
}
3 голосов
/ 03 апреля 2011

В C # вы не можете. Вы могли бы предоставить типы-потомки, которые имеют дополнительные преобразования (при условии, что типы не запечатаны); Или вы можете предоставить общий класс-обертку, который каким-то образом добавляет преобразование.

Удобство всего этого зависит от способа использования этих оболочек / адаптаций с оригинальными API.

На другой ноте Я вижу, что вы также используете F #. Предполагается, что IIRC F # обладает некоторым уровнем метапрограммирования (как и многие функциональные языки для .NET, такие как Boo и Nemerle). Меня не удивит, если это можно будет использовать здесь. К сожалению, мой F не достаточно острый, чтобы помочь там

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...