Search code examples
c#genericscastingexplicit-conversion

why does explicit cast for generic list not work


I am trying to cast a list of objects within a consturctor for a derive class IntersectionPath as follows.

    public class IntersectionPath : Path<IntersectionSegment>, IEnumerable
    {          

        //Constructors
        public IntersectionPath() : base() {  Verts = null; }

        public IntersectionPath(List<Intersection> inVerts, List<Segment<Node>> inEdges) : base() 
        {
            this.Segments = (List<IntersectionSegment>) inEdges;
        }

    }

Segments is defined in the generic base class Path

    public class Path<T> : IEnumerable<T> where T : Segment<Node>
    {   
        //public properties
        public List<Direction> Directions {get; set; }
        public List<T> Segments  {  get; set; }
    }

I have defined an explicit operator for the cast within the IntersectionSegment class (see below and so am unclear as to why this won't compile. I have an error message for the casting within the IntersectionPath constructor.

public class IntersectionSegment : Segment<Intersection>
{           
    //curves which intersect the primary curve at I0(Start Node) and I1(End Node)
    public Curve C0 { get; set; }
    public Curve C1 { get; set; }

    public IntersectionSegment():base() {}

    public IntersectionSegment(Intersection n0, Intersection n1):base(n0,n1){}

    public static explicit operator IntersectionSegment(Segment<Node> s)
    {
        if ((s.Start is Intersection) && (s.End is Intersection))
        {
            return new IntersectionSegment(s.Start as Intersection,s.End as Intersection);
        }
        else return null;
    }

    public static explicit operator List<IntersectionSegment>(List<Segment<Node>> ls)
    {
        List<IntersectionSegment> lsout = new List<IntersectionSegment>();
        foreach (Segment<Node> s in ls)
        {
            if ((s.Start is Intersection) && (s.End is Intersection))
            {
                lsout.Add(new IntersectionSegment(s.Start as Intersection,s.End as Intersection));
            }
            else return null;
        }
        return lsout;
    }

Segment is defined as:

public class Segment <T> : Shape where T : Node
{
    //generic properties
    public T Start { get; set; }
    public T End { get; set; }

 }

Solution

  • List<InteractionSegment> is not the same as InteractionSegment. Casting a list of one type to a list of another type won't cast each item.
    You need to do something like this:

    this.Segments = inEdges.Select(x => (InteractionSegment)x).ToList();
    

    This uses LINQ to Objects to cast each object in inEdges to an InteractionSegment object and puts the result back into a list that is then assigned to this.Segments.