1

假设我有以下代码:

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);

我收到一个错误,即在循环期间修改了一个集合。果然,当我单步调试调试器时,如果使用了 remove(category),“categories”列表比以前短了一个元素!为什么从“unusedCategories”中删除会影响“categories”?它们应该是两个不同的列表,而不是引用同一事物。.Remove() 函数按值传递,对吗?那么这是怎么发生的呢?

注意:我知道我在上面所做的事情有程序化的替代方案,而且我已经采用了一种。我只是好奇为什么会这样。

4

2 回答 2

9

它们应该是两个不同的列表,而不是引用相同的东西

这不是真的。当您分配categories给 时unusedCategories,您是通过引用分配。

如果你想要一个副本,你需要显式地制作一个列表的副本:

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();
于 2012-08-31T18:31:46.517 回答
0

您可以使用 来执行此操作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 描述的路径:通过分离两个集合的引用依赖关系。

于 2012-08-31T18:35:27.323 回答