简体   繁体   English

为什么对泛型列表进行显式强制转换不起作用

[英]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. 我正在尝试为派生类IntersectionPath构造一个对象内的对象列表,如下所示。

    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 细分是在通用基类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. 我已经为IntersectionSegment类中的转换定义了一个显式运算符(请参阅下文,因此不清楚为什么不进行编译。我在IntersectionPath构造函数中有一个错误消息用于转换。

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

 }

List<InteractionSegment> is not the same as InteractionSegment . List<InteractionSegment>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 . 这使用LINQ to Objects将inEdges中的每个对象inEdges转换为InteractionSegment对象,并将结果放回到列表中,然后分配给this.Segments

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. 几乎每天都会在StackOverflow上问这个问题。 Look for "covariance and contravariance" and you will find dozens of examples. 寻找“协方差和自变量”,您会发现许多示例。

It doesn't work simply because a List<Segment<Node>> is not a List<IntersectionSegment> . 它不仅仅因为List<Segment<Node>>不是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: 如果要创建更高版本,则可以使用Cast()将列表中的每个项目显式转换为所需的类型:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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