2

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

У меня есть перегруженный метод Подключен, который проверяет, что сегменты имеют общую конечную точку. Я хотел бы определить перегрузку для 2 сегментов в абстрактном сегменте, а затем для разных типов, т. Е. Сегментов и 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; 
    } 
} 

@ Джон

Так по существу ...

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

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

с

Path<T> path1 = s1 + s2; 

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

+3

В чем проблема? BTW: вы не проверяете свои входные значения на значение nullability, могут не выполняться при выполнении. –

+1

Вы все еще не объяснили, в чем проблема. Работает ли ваш текущий код? Если нет, то что делает * делает это (компилировать ошибки, исключения, ...)? – svick

ответ

1

Поскольку 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. Используйте вариант curiously recurring template pattern:

    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). Мне не нравится это решение.

+0

Спасибо, теперь лучше понял. У меня не так уж много, поэтому лучший вариант. Честно говоря, я мог выбрать этот путь вначале, но ребенок во мне хотел знать идеальный подход. var и dynamic, кажется, много всплывают ... я упускаю из виду, не зная об этом? Я только знаю до .NET 3.0 – gwizardry

+0

'var' на самом деле не изменяет ваш код. Это упрощает ваш код, поэтому вам не нужно указывать свои типы (я игнорирую анонимные типы, потому что они здесь не актуальны). 'dynamic' может быть полезна, если у вас есть переменные с некоторым типом времени компиляции, но вы хотите использовать оператор на основе их типа времени выполнения. Например, с «Сегмент s1 = новый LineSegment(), s2 = new LineSegment();', выражение 's1 + s2' будет выполнять оператор + сегмента« Сегмент ». Если вы хотите выполнить оператор 'LineSegment', вы можете использовать' (dynamic) s1 + s2'. Но я не думаю, что здесь очень полезно. – svick

Смежные вопросы