Синтаксис коллекции listbox C#

изучая C# довольно быстро, я натыкаюсь на эту проблему синтаксиса коллекции.

я добавил несколько объектов моего собственного типа MyItem в listbox lstData. Теперь мне нужно найти в этом списке и подумать об использовании элегантной нотации LINQ, например:

lstData.Items.Where(x => x.Text == SearchString)

но элементы списка не имеют a .Where (), хотя я включил "использование системы.Linq; " пространство имен.

поэтому я попытался:

foreach (MyItem item in (MyItem)lstData.Items)

но это дает ошибку построения : Нельзя преобразовать тип System.Окна.Формы.список.ObjectCollection 'to' MySandbox.frmListboxDemo.MyItem'.

мне удалось написать что-то работающее:

        for (int i = 0; i < lstData.Items.Count; i++)
        {
            MyItem item = (MyItem)lstData.Items[i];
            if (item.Text == SearchString)
            {
                lstData.SetSelected(i, true);
                break;
            }
        }

и аналогичная версия, как:

        var item_enum = lstData.Items.GetEnumerator();
        while (item_enum.MoveNext()) { etc etc... }

который оказался на 2 строки длиннее, и без выяснения, что может заменить "var".

Я не совсем уверен, что понимаю, как использовать коллекции, ObjectCollections, Перечислители и т. д., Но я хочу учиться. Особенно если .Где() версия возможна и / или лучше.


Спасибо за все ваши ответы. Я закончил с этим решением:

        var item_iter = lstData.Items.Cast<MyItem>()
                          .Where(x => x.Text.Trim().ToLower() == txtItemName.Text);
        foreach (MyItem item in item_iter)
        {
            int i = lstData.Items.IndexOf(item);
            lstData.SetSelected(i, true);
            break;
        }

Я не знаю, действительно ли это намного лучше, чем способ "fortran" (см. выше), но он учит меня методам, которые я могу использовать в других запросах c#.

4 ответов


попробуйте использовать Cast<T> сначала выполните приведение к типу, который вы ожидаете. То есть:

lstData.Items.Cast<MyItem>().Where(x => x.Text == SearchString)


коллекция элементов не является строго типизированной коллекцией. Вы можете использовать IEnumerable<T>.OfType() или IEnumerable<T>.Cast() методы расширения, чтобы получить запись в мир LINQ, где вы можете фильтровать ваши записи:

var filteredItems = lstData.Items.OfType<MyItem>().Where(i => i.Prop == val);

разница между Cast и OfType:

  • OfType<T> просто вернет элементы, которые можно кастовать, чтобы ввести T
  • Cast<T> не будет выполнена, если хотя бы один элемент в коллекции, который не приводим к Т

ListBox.ObjectCollection осуществляет IEnumerable, но не универсальный IEnumerable<T>, что требуется для большинства методов Linq.

один способ добраться до IEnumerable<T> и решить проблему литья в один шаг, чтобы использовать Cast<T>:

lstData.Items.Cast<MyItem>().Where(x => x.Text == SearchString)

попробуйте сделать список из элементов:

(new ListBox()).Items.OfType<ListViewItem>().Where(......); 

вероятно, причина в том, что он был первоначально построен с более ранней версией .net