如何将不同的对象存储在单个列表中

Tes*_*101 5 c# interface

我有两个类,一个是 Arc 类,一个是 Line 类

public class Arc
{
     protected double startx;
     protected double starty;
     protected double endx;
     protected double endy;
     protected double radius;

     public Arc(){}
}
public class Line
{
     protected double startx;
     protected double starty;
     protected double endx;
     protected double endy;
     protected double length;
     public Line(){}
}
Run Code Online (Sandbox Code Playgroud)

但我想将弧和线存储在同一个列表中,所以我尝试了这样的界面

public interface Entity
{
     double StartX();
     double StratY();
     double EndX();
     double EndY();
}
Run Code Online (Sandbox Code Playgroud)

然后,我向每个类添加了适当的方法,并添加了使用该接口的代码。现在我可以将两种类型的对象添加到列表中,但我想从线对象获取长度,并且不想向弧或界面添加长度方法。我是将线条对象转换回这样的线条对象的唯一选择吗?

List<Entity> entities = new List<Entity>();
entities.Add(new Line(10,10,5,5));
Line myLine = (Line)Entities[0]
double length = myLine.Length();
Run Code Online (Sandbox Code Playgroud)

*假设我在线路类中拥有所有正确的方法。
或者有更好/不同的方法来做到这一点?

Jul*_*iet -2

或者有更好/不同的方法来做到这一点?

如果您的对象源自公共类,那么您可以将它们存储在同一个集合中。为了对你的对象做任何有用的事情而不放弃类型安全,你需要实现访问者模式

public interface EntityVisitor
{
    void Visit(Arc arc);
    void Visit(Line line);
}

public abstract class Entity
{
    public abstract void Accept(EntityVisitor visitor);
}

public class Arc : Entity
{
    protected double startx;
    protected double starty;
    protected double endx;
    protected double endy;
    protected double radius;

    public override void Accept(EntityVisitor visitor)
    {
        visitor.Visit(this);
    }
}

public class Line : Entity
{
    protected double startx;
    protected double starty;
    protected double endx;
    protected double endy;
    protected double length;

    public override void Accept(EntityVisitor visitor)
    {
        visitor.Visit(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦完成,只要您需要对列表执行一些有用的操作,就可以创建 EntityVisitor 的实例:

class EntityTypeCounter : EntityVisitor
{
    public int TotalLines { get; private set; }
    public int TotalArcs { get; private set; }

    #region EntityVisitor Members

    public void Visit(Arc arc) { TotalArcs++; }
    public void Visit(Line line) { TotalLines++; }

    #endregion
}

class Program
{
    static void Main(string[] args)
    {
        Entity[] entities = new Entity[] { new Arc(), new Line(), new Arc(), new Arc(), new Line() };
        EntityTypeCounter counter = entities.Aggregate(
            new EntityTypeCounter(),
            (acc, item) => { item.Accept(acc); return acc; });

        Console.WriteLine("TotalLines: {0}", counter.TotalLines);
        Console.WriteLine("TotalArcs: {0}", counter.TotalArcs);
    }
}
Run Code Online (Sandbox Code Playgroud)

就其价值而言,如果您愿意尝试新语言,那么 F# 的标记联合 + 模式匹配是访问者模式的便捷替代方案