Должен ли я определить каждый оператор? - PullRequest
9 голосов
/ 19 января 2012

Предположим, у меня есть структура только с одним полем:

public struct Angle
{
    public static readonly double RadiansPerDegree = Math.PI / 180;

    private readonly double _degrees;

    public Angle(double degrees)
    {
        _degrees = degrees;
    }

    public double Degrees
    {
        get { return _degrees; }
    }

    public double Radians
    {
        get { return _degrees * RadiansPerDegree; }
    }

    public static Angle FromDegrees(double value)
    {
        return new Angle(value);
    }

    public static Angle FromRadians(double value)
    {
        return new Angle(value / RadiansPerDegree);
    }
}

Это прекрасно работает, пока я не хочу делать такие вещи:

var alpha = Angle.FromDegrees(90);
var beta = Angle.FromDegrees(100);
var inequality = alpha > beta;
var sum = alpha + beta;
var negation = -alpha;
//etc.

Итак, я реализовал IEquatable<in T> и IComparable<in T>, но они все еще не включали никаких операторов (даже ==, <, >= и т. Д.).

Итак, я начал предоставлять перегрузки оператора.

Например:

public static Angle operator +(Angle a, Angle b)
{
    return new Angle(a._degrees + b._degrees);
}

public static Angle operator -(Angle a)
{
    return new Angle(-a._degrees);
}

public static bool operator >(Angle a, Angle b)
{
    return a._degrees > b._degrees;
}

Это сработало, однако, когда я посмотрел на всех операторов, которых я мог перегрузить (+, -, !, ~, ++, --, true, false, +, -, *, /, %, &, |, ^, <<, >>, ==, !=, <, >, <=, >=), я начал чувствовать, что должен быть лучший способ. В конце концов, структура содержит только одно поле, и это поле является типом значения.

Есть ли способ включить все операторы double в одном кадре? Или мне действительно нужно вводить каждый оператор, который я мог бы хотеть поддерживать вручную?

(Даже если бы у меня было два или три поля, я все равно хотел бы добавить операторы в один пакет ...)

Ответы [ 3 ]

12 голосов
/ 19 января 2012

Смысл перегрузки операторов состоит в том, чтобы определить, как добавить для манипулирования объектами пользовательского типа эти операторы, поэтому, если бы ваше второе поле было строковым массивом, как вы ожидаете, что оператор ++ будет реализован автоматически? Ответа нет, тем более что мы не знаем контекста объекта или его использования, поэтому ответ да, вам придется перегружать операторы самостоятельно .

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

0 голосов
/ 19 января 2012

В большинстве случаев я согласен с LaceySnr: он не работает ни для каких операторов, которые возвращают ваш новый объект (например, +, * и т. Д.). Для компараторов это может сработать (так как здесь может быть аннотация, в которой говорится «используйте возвращаемое значение этого метода для замены этого объекта при использовании во всех операциях компаратора»), но я не знаю ничего подобного.

Я не уверен, каковы ограничения аннотаций в C #, но может быть возможно создать такую, которая делает это (для операторов, возвращающих bool), но если вы не планируете использовать ее очень сильно, я сомневаюсь в этом будет стоить вашего времени.

Сказав это, если у вас должен быть объект, который принимает в конструкторе ровно один аргумент, и этот аргумент является возвращаемым значением метода, то это должно быть возможно и для этого.

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

0 голосов
/ 19 января 2012

Да, вы должны определить каждый оператор, который вы хотите использовать.Компилятор не имеет возможности узнать, что вы хотите, чтобы каждый оператор делал, кроме операторов, которые являются отрицательными по отношению друг к другу (и даже те, которые не обязательно могут быть очевидны; что, если вы хотите имитировать стандартное нулевое поведение SQL, где оба ==и != вернет false по сравнению с нулем?).

...