从集合 (MembershipUserCollection) 中删除项目 - 枚举操作可能无法执行

发布于 2024-10-21 09:37:40 字数 608 浏览 1 评论 0原文

我在c#中使用asp.net 4、ef 4。 我使用 System.Web.Security 来管理 Web 应用程序中的用户。

我在 MembershipUserCollection 中有一个用户集合,我需要在该收集器上进行 foreach 期间删除一些用户。

我想当你循环时不可能从收集器中删除一个项目。 您知道如何解决吗?

请给我一个示例代码,谢谢!

       MembershipUserCollection users = Membership.GetAllUsers();
        foreach (MembershipUser x in users)
        {
            if (!Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
            {
                users.Remove(x.UserName);
            }
         }

错误:

Collection was modified; enumeration operation may not execute. 

I use asp.net 4, ef 4 in c#.
I use System.Web.Security to manage users in my web application.

I have a collection of users in MembershipUserCollection and I need remove some users during a foreach on that collector.

I suppose it is impossible to remove an item from the collector when you are looping.
Do you have any idea how to solve it?

Please provide me a sample of code, thanks!

       MembershipUserCollection users = Membership.GetAllUsers();
        foreach (MembershipUser x in users)
        {
            if (!Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
            {
                users.Remove(x.UserName);
            }
         }

Error:

Collection was modified; enumeration operation may not execute. 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

柒夜笙歌凉 2024-10-28 09:37:40

您无法在遍历枚举时对其进行修改 - 将要删除的用户放入列表中,然后在完成枚举后删除所有用户:

   MembershipUserCollection users = Membership.GetAllUsers();
   List<string> usersToRemove = new List<string>();
   foreach (MembershipUser x in users)
   {
        if (!Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
            usersToRemove.Add(x.UserName);
   }
   foreach(string userName in usersToRemove)
         users.Remove(userName);

或更短时间使用 LINQ:

var usersToRemove = Membership.GetAllUsers()
                              .Where( user => !Roles.IsUserInRole(user.UserName, "CMS-AUTHOR"))
                              .ToList();
usersToRemove.ForEach( user => users.Remove(user.UserName));

You can't modify an enumeration while traversing it - put the users to remove in a list then remove all of them once you are done enumerating:

   MembershipUserCollection users = Membership.GetAllUsers();
   List<string> usersToRemove = new List<string>();
   foreach (MembershipUser x in users)
   {
        if (!Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
            usersToRemove.Add(x.UserName);
   }
   foreach(string userName in usersToRemove)
         users.Remove(userName);

or shorter using LINQ:

var usersToRemove = Membership.GetAllUsers()
                              .Where( user => !Roles.IsUserInRole(user.UserName, "CMS-AUTHOR"))
                              .ToList();
usersToRemove.ForEach( user => users.Remove(user.UserName));
梦魇绽荼蘼 2024-10-28 09:37:40

您无法修改正在枚举的集合(显然)。尝试使用 LINQ。

users.ToList().RemoveAll(x => !Roles.InUserInRole(x.UserName, "CMS-AUTHOR"))

You cannot modify a collection you are enumerating over (obviously). Try using LINQ.

users.ToList().RemoveAll(x => !Roles.InUserInRole(x.UserName, "CMS-AUTHOR"))

依 靠 2024-10-28 09:37:40

问题在于你如何浏览集合。使用 foreach 将集合作为 IEnumerable 进行遍历。在 IEnumerable 中移动时,您所拥有的只是对当前元素的引用和移动到下一个元素的方法。当您更改可枚举的内容时,该过程就会搞砸。始终将您正在寻找的集合视为不可变的;您可以更改元素的属性,但不能通过添加或删除元素来更改集合的结构。

请尝试这样的操作:

MembershipUserCollection users = Membership.GetAllUsers();
MembershipUserCollection deletedUsers = new MembershipUserCollection();
    foreach (MembershipUser x in users)
    {
        if (!Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
        {
            deletedUsers.Add(x);
        }
     }

foreach(MembershipUser delete in deletedUsers)
{
    users.Remove(delete);
}

不同之处在于您没有更改正在枚举的集合。您可以使用一点 Linq 使这变得更简单:

MembershipUserCollection users = Membership.GetAllUsers();
//the difference is that the Select method creates a new enumerable that isolates changes to its source
foreach (MembershipUser x in users.Cast<MembershipUser>().Select(z=>!Roles.IsUserInRole(z.UserName, "CMS-AUTHOR")))
{
    users.Remove(z);
}

The problem is inherent in how you're going through the collection. Using foreach traverses the collection as an IEnumerable. When moving through the IEnumerable, all you have is a reference to the current element and a method to move you to the next one. When you change the contents of the enumerable, that process gets screwed up. Always consider the collection you are foreaching as immutable; you can change properties of elements, but you cannot change the structure of the collection by adding or removing elements.

Try something like this instead:

MembershipUserCollection users = Membership.GetAllUsers();
MembershipUserCollection deletedUsers = new MembershipUserCollection();
    foreach (MembershipUser x in users)
    {
        if (!Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
        {
            deletedUsers.Add(x);
        }
     }

foreach(MembershipUser delete in deletedUsers)
{
    users.Remove(delete);
}

The difference is that you are not changing the collection you are enumerating. You can make this simpler with a little Linq:

MembershipUserCollection users = Membership.GetAllUsers();
//the difference is that the Select method creates a new enumerable that isolates changes to its source
foreach (MembershipUser x in users.Cast<MembershipUser>().Select(z=>!Roles.IsUserInRole(z.UserName, "CMS-AUTHOR")))
{
    users.Remove(z);
}
止于盛夏 2024-10-28 09:37:40

您对问题所在的理解是正确的:在枚举集合时无法修改集合。如果允许的话,这可能会导致各种问题。

该集合应该具有 ToList()、ToArray() 或 CopyTo() 方法,该方法将创建该集合的副本。制作一个副本并循环复制该副本。然后您可以在该循环中修改原始集合。

You're right about what the problem is: You can't modify a collection while you're enumerating it. That could cause all kinds of problems if it were allowed.

The collection should have a ToList(), ToArray(), or CopyTo() method, which will create a copy of the collection. Make a copy and loop over the copy. You can then modify the original collection in that loop.

椒妓 2024-10-28 09:37:40

我可能会做类似的事情:

var usersToRemove = from user in users
                    where !Roles.IsUserInRole(x.UserName, "CMS-AUTHOR")
                    select user;

foreach(var u in usersToRemove)
{
   users.Remove(u);
}

I'd probably do something like:

var usersToRemove = from user in users
                    where !Roles.IsUserInRole(x.UserName, "CMS-AUTHOR")
                    select user;

foreach(var u in usersToRemove)
{
   users.Remove(u);
}
°如果伤别离去 2024-10-28 09:37:40

我找到了解决问题的方法。
告诉我您的想法或是否可以更好地实施。
感谢您抽出时间。

        // Take all Users
        MembershipUserCollection users = Membership.GetAllUsers();
        // Create an empty collector for only User in Author
        MembershipUserCollection usersAuthors = new MembershipUserCollection();
        foreach (MembershipUser x in users)
        {
            if (Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
            {
                usersAuthors.Add(x);
            }
        }

I found a solution to my problem.
Tell me what do you think or if could be better implemented.
Thanks for your time.

        // Take all Users
        MembershipUserCollection users = Membership.GetAllUsers();
        // Create an empty collector for only User in Author
        MembershipUserCollection usersAuthors = new MembershipUserCollection();
        foreach (MembershipUser x in users)
        {
            if (Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
            {
                usersAuthors.Add(x);
            }
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文