C# 在这些foreach循环中,如何从一个列表中删除从另一个列表中删除?

C# 在这些foreach循环中,如何从一个列表中删除从另一个列表中删除?,c#,C#,假设我有以下代码: List<Category> categories = getCategories(); List<Category> unusedCategories = categories; foreach (var category in categories) foreach (var imageCategory in image.Categories) if (category.CategoryID == i

假设我有以下代码:

List<Category> categories = getCategories();
List<Category> unusedCategories = categories;
    foreach (var category in categories)
        foreach (var imageCategory in image.Categories)
            if (category.CategoryID == imageCategory.CategoryID)
                unusedCategories.Remove(category);
我得到一个错误,在循环过程中修改了一个集合。果然,当我逐步通过调试器时,如果使用removecategory,则类别列表比以前短了一个元素!为什么从未使用的类别中删除会影响类别?它们应该是两个不同的列表,而不是引用同一事物。.Remove函数通过值传递,对吗?那么这是怎么发生的呢

注意:我知道我在上面所做的工作还有一些编程上的替代方案,我已经采用了一种。我只是好奇为什么会这样

它们应该是两个不同的列表,而不是引用同一事物

事实并非如此。将类别指定给未使用的类别时,是通过引用进行指定

如果需要副本,则需要显式复制列表:

List<Category> unusedCategories = new List<Category>(categories);
对于一个更有效的替代方案,你可以考虑一些类似的事情:

HashSet<int> usedCategoryIds = new HashSet<int>(image.Categories.Select(c => c.CategoryID));

List<Category> categories = getCategories();
List<Cagegory> unusedCategories = categories.Where(c => !usedCategoryIds.Contains(c => c.CategoryID)).ToList();
它们应该是两个不同的列表,而不是引用同一事物

事实并非如此。将类别指定给未使用的类别时,是通过引用进行指定

如果需要副本,则需要显式复制列表:

List<Category> unusedCategories = new List<Category>(categories);
对于一个更有效的替代方案,你可以考虑一些类似的事情:

HashSet<int> usedCategoryIds = new HashSet<int>(image.Categories.Select(c => c.CategoryID));

List<Category> categories = getCategories();
List<Cagegory> unusedCategories = categories.Where(c => !usedCategoryIds.Contains(c => c.CategoryID)).ToList();
您可以使用LINQ执行此操作,例如:

var removables = from category in categories
                        join imageCategory in image.Categories 
                              on category.CategoryID equals 
                                 imageCategory.CategoryID  select category;
移除后

 unusedCategories.RemoveAll(removables );
或者您可以使用for循环来避免出现异常

或者,通过分离两个集合的引用依赖项,遵循@Reed:描述的路径。

您可以使用LINQ执行此操作,例如:

var removables = from category in categories
                        join imageCategory in image.Categories 
                              on category.CategoryID equals 
                                 imageCategory.CategoryID  select category;
移除后

 unusedCategories.RemoveAll(removables );
或者您可以使用for循环来避免出现异常


或者通过分离两个集合的引用依赖项,遵循@Reed:描述的路径。

我看到的可能重复的可能重复。在这种情况下,当其他赋值(如int y=x)是按值赋值时,为什么按引用赋值?@user1442605,因为List是一个引用类型的类。C中的任何类都是引用类型,赋值都是通过引用进行的。您创建的任何结构(如Int32或Double)或自定义结构都是值类型,并按值赋值。感谢您的解释。我一直在想类和结构之间的区别是什么…我想我是通过艰苦的方式学会的。我明白了。在这种情况下,当其他赋值(如int y=x)是按值赋值时,为什么按引用赋值?@user1442605,因为List是一个引用类型的类。C中的任何类都是引用类型,赋值都是通过引用进行的。您创建的任何结构(如Int32或Double)或自定义结构都是值类型,并按值赋值。感谢您的解释。我一直在想类和结构之间的区别是什么……我想我是通过艰苦的学习才学会的。感谢这一点,很遗憾我的公司让我把.net 2.0作为目标,所以我没有接触到LINQ调用的美妙之处。@user1442605:这不是耻辱,这是商业策略。如果有一些经济上的便利,如果你能向市场营销部证明他们没有钱,明天你将有4.5版本:谢谢你,很遗憾我的公司让我把目标定为.net 2.0,所以我没有接触到LINQ呼叫的美丽。@user1442605:这不是耻辱,这是商业策略。如果有一些经济上的便利,如果你能向市场部证明他们没有钱,明天你将有4.5版本: