Лучший способ удалить элементы из коллекции - PullRequest
66 голосов
/ 16 октября 2008

Каков наилучший способ удаления элементов из коллекции в C # после того, как элемент известен, но не его индекс. Это один из способов сделать это, но в лучшем случае он выглядит не элегантным.

//Remove the existing role assignment for the user.
int cnt = 0;
int assToDelete = 0;
foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments)
{
    if (spAssignment.Member.Name == shortName)
    {
        assToDelete = cnt;
    }
    cnt++;
}
workspace.RoleAssignments.Remove(assToDelete);

Что я действительно хотел бы сделать, так это найти элемент, который нужно удалить по свойству (в данном случае, по имени), не просматривая всю коллекцию и используя 2 дополнительные переменные.

Ответы [ 14 ]

0 голосов
/ 04 сентября 2014

Как и в словарном сборе, я сделал это.

Dictionary<string, bool> sourceDict = new Dictionary<string, bool>();
sourceDict.Add("Sai", true);
sourceDict.Add("Sri", false);
sourceDict.Add("SaiSri", true);
sourceDict.Add("SaiSriMahi", true);

var itemsToDelete = sourceDict.Where(DictItem => DictItem.Value == false);

foreach (var item in itemsToDelete)
{
    sourceDict.Remove(item.Key);
}

Примечание: Выше код не будет работать в .Net Client Profile (3.5 и 4.5), и некоторые зрители отметили, что это В противном случае в .Net4.0 также не уверены, какие настройки вызывают проблему.

Поэтому замените приведенным ниже кодом (.ToList ()) для оператора Where, чтобы избежать этой ошибки. «Коллекция была изменена; операция перечисления может не выполняться. ”

var itemsToDelete = sourceDict.Where(DictItem => DictItem.Value == false).ToList();

По MSDN Начиная с .Net4.5 и далее Профиль клиента больше не поддерживается. http://msdn.microsoft.com/en-us/library/cc656912(v=vs.110).aspx

0 голосов
/ 07 мая 2012

Чтобы сделать это во время циклического перемещения по коллекции, а не чтобы получить исключение для изменения коллекции, я использовал этот подход в прошлом (обратите внимание на .ToList () в конце исходной коллекции, это создает другой коллекция в памяти, то вы можете изменить существующую коллекцию)

foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments.ToList()) { if (spAssignment.Member.Name == shortName) { workspace.RoleAssignments.Remove(spAssignment); } }

0 голосов
/ 16 октября 2008

Здесь много хороших отзывов; Мне особенно нравятся лямбда-выражения ... очень чистые. Однако я был упущен, не указав тип Коллекции. Это коллекция SPRoleAssignmentCollection (из MOSS), которая имеет только Remove (int) и Remove (SPPrincipal), а не удобный RemoveAll (). Итак, я остановился на этом, если нет лучшего предложения.

foreach (SPRoleAssignment spAssignment in workspace.RoleAssignments)
                        {
                            if (spAssignment.Member.Name != shortName) continue;
                            workspace.RoleAssignments.Remove((SPPrincipal)spAssignment.Member);
                            break;
                        }
0 голосов
/ 16 октября 2008

Существует другой подход, который вы можете использовать в зависимости от того, как вы используете свою коллекцию. Если вы загружаете назначения один раз (например, когда приложение запускается), вы можете на лету перевести коллекцию в хеш-таблицу, где:

shortname => SPRoleAssignment

Если вы сделаете это, то, когда вы захотите удалить элемент с коротким именем, все, что вам нужно сделать, это удалить элемент из хеш-таблицы по ключу.

К сожалению, если вы загружаете эти SPRoleAssignments много, это, очевидно, не будет более экономичным с точки зрения времени. Если вы пользуетесь новой версией .NET Framework, было бы хорошо, если бы вы использовали другие предложения Linq, но в остальном вам придется придерживаться используемого вами метода.

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