why does explicit cast for generic list not work

巧了我就是萌 提交于 2021-02-20 00:48:00

问题


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; }

 }

回答1:


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.




回答2:


Let's look at a far less confusing example.

class Animal {}
class Giraffe : Animal {}
class Tiger : Animal {}
...
List<Giraffe> giraffes = new List<Giraffe>();
List<Animal> animals = (List<Animal>) giraffes; // illegal

Your question is I believe "why is the cast on the last line illegal?"

Let's suppose it was legal. Now we add another line:

animals.Add(new Tiger());

You can add a tiger to a list of animals, right? But that list of animals is actually a list of giraffes. The cast does not copy the list, it says "I want to treat this object as being of this type". But since doing so would allow you to do crazy things like putting a tiger into a list of giraffes, we make the cast illegal.

Your situation is just a much more complicated version of the same situation.

This question gets asked almost every day on StackOverflow. Look for "covariance and contravariance" and you will find dozens of examples.




回答3:


It doesn't work simply because a List<Segment<Node>> is not a List<IntersectionSegment>. If you want to create the later your can use Cast() to explicitly cast each item in the list to the type you want:

this.Segments = inEdges.Cast<IntersectionSegment>().ToList();


来源:https://stackoverflow.com/questions/9891400/why-does-explicit-cast-for-generic-list-not-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!