Creating a shared list of objects in C #

As an intro, I create the base Quadtree engine for personal training purposes. I want this engine to be able to work with many different types of shapes (at the moment I'm going with circles and squares), which will move in the window and perform some action in a collision.

Here are my form objects, as I have them so far:

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

Now I ask the question how to create a general list ( List<T> QObjectList = new List<T>(); ) in C # so that I can have one list containing all of these different forms that can have different properties (e.g. QCircle has a radius property, and QSquare has a sideLength property)? An example implementation will also be useful.

I just know that there is a stupidly obvious answer to this question, but I will still be grateful for any help. I am trying to return to C #; it obviously was time ...

+8
object list generics c # quadtree
source share
8 answers

You need to use downcasting

Store objects in a list with a base class

  List<QShape> shapes = new List<QShape> 

Then you can safely improve the quality of the object if you know what it is.

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

You can also implicitly omit objects

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

See Upcasting and Downcasting for more information.

+7
source share

You must implement Interface . for example

 public interface IHasLength { int Length; } 

Then in the implementation you can do

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

FInally, on your list:

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

Now your list may contain “NOTHING” which implements IHasLength if it is QCircle , QShape or even QDuck if you want if it implements IHasLength .

+3
source share

You can save them in a List<QShape> , but that means you cannot access the type properties.

Typically, you can approach this by providing a common interface in your base class and overriding behavior in subclasses. Thus, a common interface can hide a diverse sequence of actions. For example, the Grow method can hide the complexities of growing elements of various shapes and can be called without explicit knowledge of the form on which it works.

 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; } } 
+2
source share

Is this what you want?

 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; } } } 
+2
source share

It seems to me that I missed something, but ...

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

and

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

will work just fine.

EDIT:

And, I didn’t understand what was being asked.

Yes, since your QCircle and QSquare inherit from QShape , you can just do it.

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

It is worth noting that if you want to access the radius property of the entire QCircle in this list, you will have to filter the list based on type.

+1
source share

You can use Jan Mercer's comment List<QShape>

And here is how you filled it:

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

To unpack it:

 QCircle circle = (QCircle) shapes[0]; 

If you need to call a method from the base class, you do not need to use it, just use it.

+1
source share

Preservation

You are already on the right track with your class definitions. You need to make a List superclass (in this case QShape ) that can hold all of your shapes.

Here is an example of how you will do this:

 List<QShape> objects = new List<QShape>(); objects.add(new QCircle(...)); objects.add(new QSquare(...)); 

Access

The problem here is to distinguish what used to be everything on the list. This is done using the getType() and typeof() methods for C #. ( John Skeet has a great answer on how to do this ). It basically looks like this:

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

After that, you can resume using your objects as usual. But if you try to access them from a list, you can only use the methods and variables that QShape has, since every object placed in the list will be passed to it.

-one
source share
 public Class abstract Base<T> { public abstract List<T>GetList(); } 

then do it

 public class className:Base<ObjectName> { public override List<T>GetList() { //do work here } } 
-one
source share

All Articles