C# 树中的泛型

C# 树中的泛型,c#,generics,tree,C#,Generics,Tree,我有一个segment类,它是树中的一个节点。没有树类。这棵树只是由几段组成的 public abstract class Segment { public List<Segment> Descendants { get; } => new List<Segment> Descendants; public abstract SegmentVisual VisualRepresentation { get; } } 与片段一样,该视觉对象也有子对

我有一个segment类,它是树中的一个节点。没有树类。这棵树只是由几段组成的

public abstract class Segment 
{
    public List<Segment> Descendants { get; } => new List<Segment> Descendants;
    public abstract SegmentVisual VisualRepresentation { get; }
}
与片段一样,该视觉对象也有子对象,因此可以将单个视觉对象添加到屏幕以绘制自身及其所有子对象

下面是一个实现:

public class LineSegment : Segment
{
    public LineSegment()
    {
        this.VisualRepresentation = new LineSegmentVisual(this);
    }

    public override SegmentVisual VisualRepresentation { get; }

    public Pen Stroke { get; set; }
}

我的问题是最后一节课。你可以看到重新竖琴的建议。而且我一直都觉得向下投射的感觉不太好。如果我必须在其他地方找到它的主人,我将不得不沮丧地再次获得Stroke属性

如果我将SegmentVisual设置为generic SegmentVisual,其所有者为T,则会引入一个新的障碍,因为现在SegmentVisual只能包含SegmentVisual的后代,这不应该是这样,因为我希望它包含任何类型的SegmentVisual,我只希望所有者是强类型的

我只希望SegmentVisual能够对应于特定的类,以便其所有者属性是强类型的。我似乎无法理解这一点

您可以使用new在子类中声明强类型所有者:

public class LineSegmentVisual : SegmentVisual
{
    new LineSegment Owner { get { return (LineSegment)base.Owner; } }

    public LineSegmentVisual(Segment owner)
        : base(owner)
    {
    }

    public override void RedrawItself()
    {
        using (DrawingContext ctx = this.RenderOpen())
        {
            var owner = this.Owner;
            ctx.DrawLine(owner.Stroke, this.Owner.Position, this.Owner.ControlPointPos);
        }
    }
}
这样,每次调用此.Owner时,都将铸造base.Owner,但至少可以避免重复代码

第二种方法是使用继承。使用基本功能声明SegmentVisual

abstract class SegmentVisual
{
    public List<SegmentVisual> Descendants { get; private set; }

    ...
}
Owner可以在子类中使用,而无需强制转换,公共功能只需使用SegmentVisual即可

第三种方法是使用泛型协方差,但必须为类型声明接口:

public class Program
{
    public static void Main()
    {
        var sv = new LineSegmentVisual();
        sv.Descendants = new List<ISegmentVisual<Segment>> { new SquareSegmentVisual() };
    }
}


abstract class Segment {}

class LineSegment : Segment {}

class SquareSegment: Segment {}

interface ISegmentVisual<out TOwner>
{
    TOwner Owner { get; }

    List<ISegmentVisual<Segment>> Descendants { get; }
}

class LineSegmentVisual : ISegmentVisual<LineSegment>
{
    public LineSegment Owner { get; set; }
    public List<ISegmentVisual<Segment>> Descendants { get; set; }
}

class SquareSegmentVisual : ISegmentVisual<SquareSegment>
{
    public SquareSegment Owner { get; set; }
    public List<ISegmentVisual<Segment>> Descendants { get; set; }
}

希望,这会有所帮助。

C不支持返回类型差异。也就是说,以下情况是不可能的:

class Foo
{
    virtual Base Owner{ get; }
}

class Bar: Foo
{
    override Derived Owner { get; } // where Dervided: Base
}
您将得到一个编译时错误,通知您派生的方法不会覆盖任何合适的方法。老实说,我发现C中缺少这个功能有点恼人,尽管它在未来的版本中已经上线几次了,但它从来没有成功过。老实说,竞争的功能已经更新了很多,更加有趣和有用

在我看来,你有两个合理的选择。一种是隐藏所有者:

另一种是使用显式实现的接口:

interface IOwnable
{
    Base Owner { get; }
}

class Foo: IOwnable
{
    Base IOwnable.Owner { get; }
}

class Bar: Foo
{
    Derived Owner { get { return ((IOwnable)base).Owner as Derived; } // where Derived: Base
}

谢谢,今晚晚些时候我会看一看并通知你:我使用了第二种方法,它解决了问题。感谢s:
public class Program
{
    public static void Main()
    {
        var sv = new LineSegmentVisual();
        sv.Descendants = new List<ISegmentVisual<Segment>> { new SquareSegmentVisual() };
    }
}


abstract class Segment {}

class LineSegment : Segment {}

class SquareSegment: Segment {}

interface ISegmentVisual<out TOwner>
{
    TOwner Owner { get; }

    List<ISegmentVisual<Segment>> Descendants { get; }
}

class LineSegmentVisual : ISegmentVisual<LineSegment>
{
    public LineSegment Owner { get; set; }
    public List<ISegmentVisual<Segment>> Descendants { get; set; }
}

class SquareSegmentVisual : ISegmentVisual<SquareSegment>
{
    public SquareSegment Owner { get; set; }
    public List<ISegmentVisual<Segment>> Descendants { get; set; }
}
class Foo
{
    virtual Base Owner{ get; }
}

class Bar: Foo
{
    override Derived Owner { get; } // where Dervided: Base
}
class Bar: Foo
{
    new Derived Owner { get { return base.Owner as Derived; } // where Derived: Base
}
interface IOwnable
{
    Base Owner { get; }
}

class Foo: IOwnable
{
    Base IOwnable.Owner { get; }
}

class Bar: Foo
{
    Derived Owner { get { return ((IOwnable)base).Owner as Derived; } // where Derived: Base
}