gpt4 book ai didi

c# - 树中的泛型

转载 作者:行者123 更新时间:2023-11-30 23:24:56 29 4
gpt4 key购买 nike

我有一个段类,它是树中的一个节点。没有 Tree类(class)。这棵树只是由片段组成。

public abstract class Segment 
{
public List<Segment> Descendants { get; } => new List<Segment> Descendants;
public abstract SegmentVisual VisualRepresentation { get; }
}

SegmentVisual是一个用于将片段绘制到屏幕上的类。这两个类都是抽象的,因为我有不同类型的线段,每个线段都需要以不同的方式绘制。

这是如何SegmentVisual看起来像:

public abstract class SegmentVisual : DrawingVisual 
{
protected SegmentVisual(Segment owner){
this.Owner = owner;
}

public Segment Owner { get; }
public List<SegmentVisual> Descendants { get; } = new List<SegmentVisual>();

public void Redraw()
{
this.RedrawItself();

foreach (SegmentVisual visual in this.Visuals)
{
visual.Redraw();
}
}

public abstract void RedrawItself();
}

就像段一样,视觉对象也有后代,因此可以将单个视觉对象添加到屏幕以绘制自身及其所有后代

这是一个实现:

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

public override SegmentVisual VisualRepresentation { get; }

public Pen Stroke { get; set; }
}

.

public class LineSegmentVisual : SegmentVisual
{
public LineSegmentVisual(LineSegment owner) // Resharper suggests this can be Segment base class
: base(owner)
{
}

public override void RedrawItself()
{
using (DrawingContext ctx = this.RenderOpen())
{
var owner = (LineSegment)this.Owner;
ctx.DrawLine(owner.Stroke, this.Owner.Position, this.Owner.ControlPointPos);
}
}
}

我的问题是最后一节课。你可以看到 ReSharper 建议。而且我一直对向下类型转换感觉不太好。如果我必须在其他某个地方检索所有者,我将不得不沮丧以再次获取 Stroke 属性。

如果我做 SegmentVisual通用 SegmentVisual<T> ,它的所有者是 T ,它引入了一个新的障碍,因为现在 SegmentVisual只能包含 SegmentVisual<T> 的后代事实并非如此,因为我希望它包含任何类型的 SegmentVisual ,我只希望所有者是强类型的。

我只想要 SegmentVisual能够对应到一个特定的类,使其Owner属性是强类型的。我似乎无法弄清楚这一点。

最佳答案

您可以使用 new 在您的子类中声明强类型的 Owner:

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

这样,每次调用 this.Owner 时,都会强制转换 base.Owner,但至少可以避免重复代码。


第二种方式是使用继承。声明具有基本功能的 SegmentVisual

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

...
}

和具有强类型所有者的OwnedSegmentVisual

abstract class OwnedSegmentVisual<TOwner>: SegmentVisual where TOwner: Segment
{
public TOwner Owner { get; private set; }

protected OwnedSegmentVisual(TOwner owner)
{
Owner = owner;
}
}

Owner 无需转换即可在子类中使用,常用功能只需使用 SegmentVisual


第三种方法是使用泛型协变,但您必须为您的类型声明接口(interface):

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# - 树中的泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37526360/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com