9

作为介绍,我正在为个人学习目的创建一个基本的四叉树引擎。我希望这个引擎能够处理许多不同类型的形状(目前我正在使用圆形和正方形),它们都将在窗口中移动并在发生碰撞时执行某种动作。

这是我目前拥有的形状对象:

public class QShape {
    public int x { get; set; }
    public int y { get; set; }
    public string colour { get; set; }
}

public class QCircle : QShape {
    public int radius;
    public QCircle(int theRadius, int theX, int theY, string theColour) {
        this.radius = theRadius;
        this.x = theX;
        this.y = theY;
        this.colour = theColour;
    }
}

public class QSquare : QShape {
    public int sideLength;
    public QSquare(int theSideLength, int theX, int theY, string theColour) {
        this.sideLength = theSideLength;
        this.x = theX;
        this.y = theY;
        this.colour = theColour;
    }
}

现在我的问题是,如何List<T> QObjectList = new List<T>();在 C# 中创建一个通用列表( )? 一个实现的例子也会有帮助。

我只知道这个问题有一个愚蠢的答案,但无论如何我都会很感激任何帮助。我正在尝试回到 C#;显然已经有一段时间了……

4

8 回答 8

7

您需要使用向下转换

将对象存储在带有基类的列表中

 List<QShape> shapes = new List<QShape>

然后,如果您知道对象是什么,则可以安全地向上转换对象,例如

if(shapes[0] is QSquare)
{
     QSquare square = (QSquare)shapes[0]
} 

您还可以隐式向下转换对象

QSquare square = new Square(5,0,0,"Blue");
QShape shape =  square

有关更多信息,请阅读此处的向上转换和向下转换部分

于 2012-07-06T01:14:35.300 回答
3

你应该实现一个Interface. 例如

public interface IHasLength
{
    int Length;
}

然后在实现中你可以做

public class QSquare : QShape, IHasLength {
    public int sideLength;
    public QSquare(int theSideLength, int theX, int theY, string theColour) {
        this.sideLength = theSideLength;
        this.x = theX;
        this.y = theY;
        this.colour = theColour;
    }
    public int Length { get { return sideLength; } }
}
public class QCircle : QShape, IHasLength {
    public int radius;
    public QSquare(int theSideLength, int theX, int theY, string theColour) {
        this.sideLength = theSideLength;
        this.x = theX;
        this.y = theY;
        this.colour = theColour;
    }
    public int Length { get { return radius; } }
}

最后,在您的列表中:

List<IHasLength> shapesWithSomeLength = new List<IHasLength>();

现在,您的列表可以包含任何实现的内容,IHasLength无论它是 a QCircleQShape,甚至是QDuck您想要的 a ,只要它实现了IHasLength

于 2012-07-06T01:15:24.223 回答
3

这是你想要的吗?

public class QShape
{
    protected QShape() { }
    public int x { get; set; }
    public int y { get; set; }
    public string colour { get; set; }
}

public class QCircle : QShape
{
    public int radius;
    public QCircle(int theRadius, int theX, int theY, string theColour)
    {
        this.radius = theRadius;
        this.x = theX;
        this.y = theY;
        this.colour = theColour;
    }
}

public class QSquare : QShape
{
    public int sideLength;
    public QSquare(int theSideLength, int theX, int theY, string theColour)
    {
        this.sideLength = theSideLength;
        this.x = theX;
        this.y = theY;
        this.colour = theColour;
    }
}
class Program
{
    static void Main(string[] args)
    {
        List<QShape> list = new List<QShape>();
        list.Add(new QCircle(100, 50, 50, "Red"));
        list.Add(new QCircle(100, 400, 400, "Red"));
        list.Add(new QSquare(50, 300, 100, "Blue"));


        foreach (var item in list.OfType<QCircle>())
        {
            item.radius += 10;
        }

        foreach (var item in list.OfType<QSquare>())
        {
            item.sideLength += 10;
        }
    }
}
于 2012-07-06T02:00:41.950 回答
2

您可以将它们存储在 a 中List<QShape>,但这意味着您无法访问特定于类型的属性。

通常,您可以通过在基类中提供公共接口并在子类中覆盖行为来解决此问题。通过这种方式,一个通用的界面可以隐藏各种不同的行为。例如,一个Grow方法可以隐藏不同形状的增长项目的复杂性,并且可以在不明确知道它正在操作的形状的情况下调用。

public abstract class QShape {
    public abstract void Grow(int amt);
}
public class QSquare : QShape {
    private int sideLength;
    public override void Grow(int amt)
    {
        sideLength+=amt;
    }
}
public class QCircle : QShape {
    private int radius;
    public override void Grow(int amt)
    {
        radius+=amt;
    }
}
于 2012-07-06T01:15:49.213 回答
1

我觉得我错过了一些东西,但是......

List<QCircle> circleObjects = new List<QCircle>();

List<QSquare> squareObjects = new List<QSquare>();

会很好地工作。

编辑:

啊,没看懂在问什么。

是的,因为你QCircleQSquare类继承自QShape,你可以这样做。

List<QShape> shapes= new List<QShape>();

值得注意的是,如果您想访问该列表radius中所有QCircle' 的属性,那么您将不得不根据类型过滤列表。

于 2012-07-06T01:09:15.023 回答
1

您可以使用 Ian Mercer 的评论List<QShape>

以下是你将如何填写它:

List<QShape> shapes = new List<QShape>();
QCircle circle = new QCircle(); 

shapes.Add(circle);

拆箱:

QCircle circle = (QCircle) shapes[0];

如果需要从基类中调用方法,无需拆箱,直接使用即可。

于 2012-07-06T01:13:19.270 回答
-1

存储

您的类定义已经走在正确的轨道上。您需要做的是创建一个List超类(在本例中为QShape),它将能够容纳您的所有形状。

这是一个如何制作它的示例:

List<QShape> objects = new List<QShape>();

objects.add(new QCircle(...));
objects.add(new QSquare(...));

访问

这里的问题是区分列表中的所有内容后是什么。这是通过C#的getType()and方法完成的。typeof()乔恩斯基特对如何做到这一点有一个很好的答案)。基本上,它看起来像这样:

if(objects.get(some_position).getType() == typeof(QCircle))
  QCircle circle = objects.get(some_position);
else if(/* like above with QSquare */)
  QSquare square = objects.get(some_position);

完成此操作后,您可以像平常一样继续使用您的对象。但是,如果您尝试从列表中访问它们,则只能使用具有的方法和变量QShape,因为放入列表中的每个对象都将被强制转换为它。

于 2012-07-06T01:20:24.237 回答
-1
public Class abstract  Base<T>
{
    public abstract List<T>GetList();
}

然后这样做

public class className:Base<ObjectName>
{
    public override List<T>GetList()
    {
        //do work here 
    }
}
于 2014-10-24T10:43:10.460 回答