InvalidCastException в результате индексации в ArrayList - PullRequest
4 голосов
/ 15 февраля 2010

У меня есть ArrayList, заполненный кучей точек, и я хочу зациклить их, поэтому я использую этот код:

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

и я получаю эту ошибку в строках clickPos и prevPos:

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

Почему это? У меня clickPos и prevPos определены так:

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

Редактировать

Когда я закомментирую строки clickPos и prevPos и добавлю

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

в окне сообщения написано System.Drawing.Point

Ответы [ 8 ]

6 голосов
/ 15 февраля 2010

Вы должны использовать общий List<Point> вместо ArrayList.

Если вы настаиваете на использовании ArrayList, вам нужно привести объекты к Point, когда вы их получите:

clickPos = (Point)currentClicks[i];
4 голосов
/ 15 февраля 2010

Попробуйте это:

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

Лучшим решением может быть использование общего списка, List<Point>, тогда вам вообще не понадобится приведение.

3 голосов
/ 15 февраля 2010

ArrayLists не являются строго типизированными. Они в основном IList из object.

Из-за этого вам нужно привести ваши ссылки на элементы массива к тому типу, который вы знаете.

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

Я бы настоятельно рекомендовал использовать List<Point> вместо ArrayList. Это даст вам строго типизированный список очков и избавит вас от необходимости разыгрывать ваши ссылки.

Универсальный List<T> также предлагает те же функции, что и ArrayList, но, как правило, с более высокой производительностью. Из документации:

Вопросы производительности

При принятии решения использовать ли Список или Класс ArrayList, оба из которых имеют похожая функциональность, помните, что класс List работает лучше в большинстве случаи и тип безопасны. Если ссылка тип используется для типа T Списка класс, поведение двух классов идентично.

2 голосов
/ 15 февраля 2010

Почему бы вам не начать с 1?

for (int i = 1; i < currentClicks.Count; i++) 
{ 
         clickPos = (System.Drawing.Point)currentClicks[i];
        prevPos = (System.Drawing.Point)currentClicks[i - 1];
} 
1 голос
/ 15 февраля 2010

Относительно вашего редактирования: вы знаете, что ArrayList содержит точки, а среда выполнения знает, что ArrayList содержит точки (отсюда и результат .GetType()), но компилятор не знает, что arraylist держит очки. Вам нужен приведение там, чтобы удовлетворить компилятор.

Но на самом деле, единственный правильный способ исправить это - изменить его на общий List<Point>.

0 голосов
/ 15 февраля 2010

Если вы не застряли в .NET 1.1 или не имеете никакого контроля над созданием списка, вам будет лучше использовать List<Point>

ArrayList требует, чтобы вы использовали явные приведения для получения членов, если вы не хотите использовать их просто как объект, поэтому вам нужно это

clickPos = (Point)currentClicks[i];
prevPos = (Point)currentClicks[i - 1];
0 голосов
/ 15 февраля 2010

ArrayList содержит ссылки на объекты, и вы пытаетесь неявно привести эти объекты к точкам. Вы можете либо явно привести, как показывает Ник, либо использовать вместо него общий List<T>, что я бы порекомендовал:

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

Использование общего списка (добавлено в .NET в 2.0, описание здесь ) позволяет работать с объектами гораздо более безопасным для типов способом без приведения во время выполнения. Если вы работаете с .NET 2.0 или выше, вы никогда не должны использовать ArrayList, Hashtable или любые другие неуниверсальные конструкции.

0 голосов
/ 15 февраля 2010

Код Ника сработает, или вы можете попробовать:

ArrayList<System.Drawing.Point>

ArrayList реализует IEnumerable, что означает, что он всегда возвращает System.Object. ArrayList<T> реализует IEnumerable и всегда возвращает T.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...