简体   繁体   中英

Operator overloading polymorphism returning generic collection

I want to overload the + operator for adding segments together to form a Path. I've defined a Path where T is Segment and contains a List (where naturally T is Segment). Segment is an abstract base class for various types of Segment ie LineSegment

I have an overloaded method Connected which checks that the segments have a common end point. I'd like to define the overload for 2 Segments in the abstract Segment class and then for different types ie Segment and LineSegment within the respective derived classes.

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

So essentially...

I'm trying to replace the following code (path1 is a Path, Segments is a List where T is Segment).

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

with

Path<T> path1 = s1 + s2;

The problem is that with the code does not compile.

Since C# doesn't support generic operators, I think there is no simple way to do this. But I can imagine several ways to make it work:

  1. Don't do this. As Jon suggested, you could always return a Path<Segment> , even if you add, say, two LineSegment s. I don't like this “solution”, because it could mean you would have to use casts all over the place.

  2. Add the operator to every type that inherits from Segment . This means repeating code, but I think it's the best option here. For example, the operator for LineSegment would look like this:

     public static Path<LineSegment> operator +(LineSegment s1, LineSegment s2) 
  3. Don't add two segments together, but instead add them to an empty path. If you do this, it would be probably best if you made Path immutable:

     var path = Path<LineSegment>.Empty + lineSegment1 + lineSegment2; 
  4. Use a variant of the 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> { } 

    If you do this, you don't have any repetition, but it feels like a hack and it could complicate your inheritance hierarchy a lot (you can't inherit from a class that specifies T ). I don't like this solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM