views:

117

answers:

8

I have an ArrayList filled with a bunch of Points and I want to loop over them, so I use this code:

for (int i = 0; i < currentClicks.Count; i++)
{
    if (i > 0) // Skip the first click
    {
        clickPos = currentClicks[i];
        prevPos = currentClicks[i - 1];
    }
}

and I get this error on the clickPos and prevPos lines:

Cannot implicitly convert type 'object' to 'System.Drawing.Point'.
An explicit conversion exists (are you missing a cast?)

Why is this? I have clickPos and prevPos defined as so:

private System.Drawing.Point clickPos;
private System.Drawing.Point prevPos;

Edit

When I comment out the clickPos and prevPos lines and add

MessageBox.Show(currentClicks[i].GetType().ToString());

the message box says System.Drawing.Point

+4  A: 

Try this:

for (int i = 1; i < currentClicks.Count; i++)
{
    clickPos = (System.Drawing.Point)currentClicks[i];
    prevPos = (System.Drawing.Point)currentClicks[i - 1];
}

A better solution could be using a generic list, a List<Point>, then you wouldn't need the cast at all.

Nick Craver
@Jeff - Agreed, updated!
Nick Craver
+6  A: 

You should use the generic List<Point> instead of an ArrayList.

If you insist on using an ArrayList, you'll need to cast the objects to a Point when you retrieve them:

clickPos = (Point)currentClicks[i];
Anon.
Dear God, yes; use a List<Point>. +1. The only reason ever to use an ArrayList in VS2008 is for compatibility with the Settings file. Also, once you have the List<Point>, iterate over it with a foreach loop rather than a for loop.
Joel Coehoorn
Switching to List<T> worked. Thanks!
c00lryguy
+2  A: 

Why wouldn't you just start with 1?

for (int i = 1; i < currentClicks.Count; i++) 
{ 
         clickPos = (System.Drawing.Point)currentClicks[i];
        prevPos = (System.Drawing.Point)currentClicks[i - 1];
} 
JBrooks
=p Good idea. I'm from a Ruby background, so I'm not used to all of these for loops
c00lryguy
+3  A: 

ArrayLists are not strongly typed. They are basically an IList of object.

Because of this, you need to cast your references to the arraylist elements to the type that you know they are.

    clickPos = (Point)currentClicks[i];
    prevPos = (Point)currentClicks[i - 1];

I would strongly recommend using a List<Point> rather than an ArrayList. This will give you a strongly typed list of Points and remove the requirement for having to cast your references.

A generic List<T> also offers the exact same functionality as an ArrayList, but generally with better performance. From the documentation:

Performance Considerations

In deciding whether to use the List or ArrayList class, both of which have similar functionality, remember that the List class performs better in most cases and is type safe. If a reference type is used for type T of the List class, the behavior of the two classes is identical.

womp
A: 

Nick's code will work, or you could try using:

ArrayList<System.Drawing.Point>

The ArrayList implements IEnumerable, which means it always hands back System.Object. ArrayList<T> implements IEnumerable and will always hand back a T.

BnWasteland
ArrayList is non-generic. Did you mean to suggest `List<Point>`? That would return a strongly typed `T` without the need to cast the object.
Ahmad Mageed
A: 

An ArrayList contains references to objects, and you're attempting to implicitly cast those objects to Points. You can either explicitly cast, as Nick shows, or use a generic List<T> instead, which is what I would recommend:

List<Point> currentClicks = new List<Point>();
// add your points

Using a generic List (added to .NET in 2.0, described here) allows you to work with objects in a much more type-safe manner, without runtime casts. If you're working with .NET 2.0 or greater, you should never use ArrayList, Hashtable, or any of the other non-generic constructs.

Michael Petrotta
A: 

Unless you are stuck on .NET 1.1 or have no control over the creation of the list, you would be better off with List<Point>

the ArrayList requires that you use explict casts to get at the members unless you want to use them simply as object, so you need this

clickPos = (Point)currentClicks[i];
prevPos = (Point)currentClicks[i - 1];
John Knoeller
+1  A: 

Regarding your edit: you know the ArrayList holds points, and the runtime knows the ArrayList holds points (hence the .GetType() result), but the compiler does not know the arraylist holds points. You need a cast there to satisfy the compiler.

But really, the only correct way to fix this is to change it to a generic List<Point>.

Joel Coehoorn
I see, that makes sense.
c00lryguy