Перегрузка операторов полиморфизмом, возвращающим универсальную коллекцию - PullRequest
2 голосов
/ 18 марта 2012

Я хочу перегрузить оператор + для добавления сегментов вместе, чтобы сформировать путь. Я определил путь, где T является сегментом и содержит список (где, естественно, T является сегментом). Сегмент - это абстрактный базовый класс для различных типов сегмента, то есть LineSegment

У меня есть перегруженный метод Connected, который проверяет, что сегменты имеют общую конечную точку. Я хотел бы определить перегрузку для 2 сегментов в абстрактном классе Segment, а затем для различных типов, то есть Segment и LineSegment в соответствующих производных классах.

public static Path<T> operator +(Segment s1, Segment s2)
{
    if (s1.Connected(s2))
    {
        List<Segment> slist = new List<Segment>();
        slist.Add(s1);
        slist.Add(s2);
        Path<T> p = new Path<T>(slist);
        return p;
    }
    else
    {
        return null;
    }
}

@ Jon

Так по сути ...

Я пытаюсь заменить следующий код (путь1 - это путь, сегмент - это список, где T - это сегмент).

Path<T> path1 = new Path<T>(s1);
path1.Segments.Add(s2);

с

Path<T> path1 = s1 + s2;

Проблема в том, что с кодом не компилируется.

1 Ответ

1 голос
/ 18 марта 2012

Поскольку C # не поддерживает универсальные операторы, я думаю, что не существует простого способа сделать это.Но я могу представить несколько способов заставить его работать:

  1. Не делайте этого.Как предположил Джон, вы всегда можете вернуть Path<Segment>, даже если вы добавите, скажем, два LineSegment с.Мне не нравится это «решение», потому что оно может означать, что вам придется использовать повсеместное приведение типов.

  2. Добавьте оператор к каждому типу, который наследуется от Segment.Это означает повторение кода, но я думаю, что это лучший вариант здесь.Например, оператор для LineSegment будет выглядеть следующим образом:

    public static Path<LineSegment> operator +(LineSegment s1, LineSegment s2)
    
  3. Не добавляйте два сегмента вместе, а вместо этого добавляйте их в пустой путь.Если вы сделаете это, вероятно, было бы лучше, если бы вы сделали Path неизменяемым:

    var path = Path<LineSegment>.Empty + lineSegment1 + lineSegment2;
    
  4. Используйте вариант любопытно повторяющегося шаблона :

    class SegmentBase<T> where T : SegmentBase<T>
    {
        public static Path<T> operator +(SegmentBase<T> s1, SegmentBase<T> s2)
        {
            return new Path<T>(new List<T> { (T)s1, (T)s2 });
        }
    }
    
    class LineSegment : SegmentBase<LineSegment>
    { }
    

    Если вы сделаете это, у вас не будет повторений, но это похоже на хак, и это может сильно усложнить вашу иерархию наследования (вы не можете наследовать от класса, который определяет T).Мне не нравится это решение.

...