#c# #list #.net-3.5 #extension-methods #windows-ce
#c# #Список #.net-3.5 #методы расширения #windows-ce
Вопрос:
Итак, я попытался создать некоторые базовые методы расширения для List
. По сути, у меня есть UniqueAdd и UniqueAddRange. Он проверит наличие значения перед добавлением, и если оно уже есть в списке, оно его не добавит. Вот код:
public static class ListExtensions
{
/// <summary>
/// Adds only the values in the 'values' collection that do not already exist in the list. Uses list.Contains() to determine existence of
/// previous values.
/// </summary>
/// <param name="list"></param>
/// <param name="values"></param>
public static void UniqueAddRange<T>(this List<T> list, IEnumerable<T> values)
{
foreach (T value in values)
{
list.UniqueAdd(value);
}
}
/// <summary>
/// Adds the value to the list only if it does not already exist in the list. Uses list.Contains() to determine existence of previos values.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="value"></param>
public static void UniqueAdd<T>(this List<T> list, T value)
{
if (!list.Contains(value))
{
list.Add(value);
}
}
}
И я получаю следующую ошибку при сборке:
CA0001 : Rule=Microsoft.Maintainability#CA1506, Target=Some.Namespace.ListExtensions : Collection was modified; enumeration operation may not execute.
Вот ссылка на ошибку, но я не уверен, как исправить мои методы расширения, учитывая эту информацию. В нем говорится, что
Попробуйте изменить тип или метод, чтобы уменьшить количество типов, с которыми он связан.
Кто-нибудь знает, почему я получаю эту ошибку и как исправить мои методы расширения, чтобы они не нарушали это правило?
Спасибо!
PS: Прежде чем кто-либо упомянет об этом, я рассмотрел возможность использования HashSet, но HashSet не существует в compact framework.
Ответ №1:
Я думаю, что ваш код вызвал ошибку в FxCop, «Коллекция была изменена» — это классический упс. Затем он решил, что его ошибка была вашей проблемой, стиль catch (исключение).
Ищите обновление. Тот, который я использую, не жалуется на ваш код (версия VS2010).
Комментарии:
1. Психическая отладка не часто приветствуется: (
Ответ №2:
Он сообщает вам, что вы меняете список при его перечислении. Это ясно из вашего кода (вы добавляете в список одновременно с перечислением).
Как насчет:
public static void UniqueAddRange<T>(this List<T> list, IEnumerable<T> values)
{
list.AddRange(values.Except(list));
}
Или, если интерфейс подходит для ваших нужд, используйте Hashset . Он делает то, что вы хотите, прямо из коробки.
Комментарии:
1. Спасибо, я попробую. Я забыл, что Contains будет непреднамеренно перечислять список, поэтому я получаю эту проблему. Что касается HashSet, я упомянул в своем сообщении, что он не существует в compact framework.
2. Нет, вы видите эту проблему, потому что цикл foreach в
UniqueAddRange
повторяет перечисление, которое изменяется под его ногами. Заметил проблему с набором хэшей, отсюда и зачеркивание 😉 Способ LINQ также должен быть быстрее, потому что ему не нужно проверять весь список для каждой вставки.3. Я не думаю, что это правильно:
values
иlist
— это два полностью отдельных списка, и я только повторяюvalues
, я никогда не изменяю его. Я только изменяюlist
.4. Ах, да. Мой плохой. Я должен идти спать сейчас, так как я бесполезен! Рискну предположить, что предоставленный мной код, вероятно, более эффективен. Похоже, @Hans может быть прав.
5. Я не сомневаюсь, что в полном объеме . NET framework это так, но, на удивление, compact framework работает довольно медленно с LINQ.