Перегрузка операторов в универсальной структуре: могу ли я создать перегрузки для определенных видов (?) Универсальных? - PullRequest
4 голосов
/ 10 января 2011

Я определяю физические единицы в C #, используя общие структуры, и все шло нормально, пока я не получил ошибку:

Одним из параметров бинарного оператора должен быть содержащий тип

при попытке перегрузить математические операторы, чтобы они конвертировали между различными единицами. Итак, у меня есть что-то вроде этого:

public interface ScalarUnit { }
public class Duration : ScalarUnit { }

public struct Scalar<T> where T : ScalarUnit
{
    public readonly double Value;

    public Scalar(double Value)
    {
        this.Value = Value;
    }

    public static implicit operator double(Scalar<T> Value)
    {
        return Value.Value;
    }
}

public interface VectorUnit { }
public class Displacement : VectorUnit { }
public class Velocity : VectorUnit { }

public struct Vector<T> where T : VectorUnit
{
    #...

    public static Vector<Velocity> operator /(Vector<Displacement> v1, Scalar<Duration> v2)
    {
        return new Vector<Velocity>(v1.Magnitude / v2, v1.Direction);
    }
}

Нет ошибок для операторов + и -, где я просто работаю над Vector<T>, но когда я заменяю единицу на T, внезапно это не нравится , Есть ли способ сделать эту работу?

Я подумал, что это сработает, поскольку Displacement реализует интерфейс VectorUnit, и у меня есть where T : VectorUnit в заголовке структуры. Я хотя бы на правильном пути здесь? Я новичок в C #, поэтому мне трудно понять, что происходит иногда.

1 Ответ

2 голосов
/ 10 января 2011

Я не думаю, что операторы могут быть общими.

Возможно, я бы рассмотрел жесткое кодирование типов в операторе, т. Е. Если typeof (T) .GetGenericParameters () [0] - это тот или иной тип, бла-бла.

Другой подход, который я бы даже предпочел, - реализовать общий интерфейс / базовый класс во всех подклассах, который возвращает значение типа double, а затем от оператора вы приводите его к этому интерфейсу / b. класс и получить значения для расчета.

Примечание: по соглашению имена интерфейсов всегда должны начинаться с I (пример: IScalarUnit).

...