Home > Software engineering >  C# - After executing the remove statement , list stays the same
C# - After executing the remove statement , list stays the same

Time:09-29

Everyone , I tried to remove item based on condition but it seems that after executing the remove statement my list stays the same .

class Menu

  public class Menu : Entity
{
    /// <summary>
    /// Tạo mới guid khi gọi tới menu
    /// </summary>
    public Menu()
    {
        Random rnd = new Random();
        Id = rnd.Next(1,999999) * DateTime.Now.Millisecond;
        Guid = Guid.NewGuid();
    }
    /// <summary>
    /// Danh sách Role
    /// </summary>
    [Required(ErrorMessage = nameof(EnumManageMenu.ENM01))]
    public ICollection<string> Roles { get; set; }
    /// <summary>
    /// Danh sách Permisions
    /// </summary>
    [Required(ErrorMessage = nameof(EnumManageMenu.ENM02))]
    public ICollection<string> Permisions { get; set; }
    /// <summary>
    /// Tên của từng menu
    /// </summary>
    [Required(ErrorMessage = nameof(EnumManageMenu.ENM03))]
    [MaxLength(200, ErrorMessage = nameof(EnumManageMenu.ENM07))]
    public string Name { get; set; }
    /// <summary>
    /// Đường dẫn
    /// </summary>
    [Required(ErrorMessage = nameof(EnumManageMenu.ENM09))]
    [MaxLength(1000, ErrorMessage = nameof(EnumManageMenu.ENM08))]
    public string Link { get; set; }
    /// <summary>
    /// Mỗi menu sẽ chứa một loại menu
    /// </summary>
    public ICollection<Menu> Items { get; set; }
    /// <summary>
    /// Mô tả thêm của từng menu
    /// </summary>
    [MaxLength(2000, ErrorMessage = nameof(EnumManageMenu.ENM11))]
    public string Description { get; set; }
    /// <summary>
    /// Loại menu
    /// </summary>
    [Required(ErrorMessage = nameof(EnumManageMenu.ENM03))]
    [MaxLength(1000, ErrorMessage = nameof(EnumManageMenu.ENM013))]
    public string EnumCode { get; set; }

    /// <summary>
    /// Icon của menu
    /// </summary>
    [Required(ErrorMessage = nameof(EnumManageMenu.ENM016))]
    [MaxLength(1000, ErrorMessage = nameof(EnumManageMenu.ENM017))]
    public string Icon { get; set; }

    /// <summary>
    /// Trạng thái của menu
    /// </summary>       
    public bool Active { get; set; }

    /// <summary>
    /// Sắp xếp danh sách menu
    /// </summary>
    public int SortOrder { get; set; }


}

below is my code

 public async Task<MethodResult<List<MenuModel>>> GetAllMenuAsync()
    {
        MethodResult<List<MenuModel>> methodResult = new MethodResult<List<MenuModel>>();
        List<Menu> empty = new List<Menu>();
        List<Menu> menus = await _dbCollection.Find(FilterDefinition<Menu>.Empty).ToListAsync();
        empty = menus;
        int countList = menus.Count;
        for (int i = 0; i < countList; i  )
        {
            foreach (var item in GetListNoDel(menus[i]))
            {
                if (item.IsDeleted)
                {
                    empty.Remove(item);
                }
            }
        }
        List<MenuModel> menuModels = _mapper.Map<List<MenuModel>>(empty);
        methodResult.Result = menuModels;
        return methodResult;
    }
    private IEnumerable<Menu> GetListNoDel(Menu menus)
    {
        yield return menus;
        foreach (var item in menus.Items)
        {
            foreach (var items in GetListNoDel(item))
            {
                    yield return items;
            }
        }
    }

enter image description here

CodePudding user response:

You cannot "foreach" over a list and immediately remove items (as you undoubtedly know). So you will have to first find the items to remove, and then remove them. A twist in your case is that those "items to remove" can be at any depth in a menu tree.

So when you find an item to remove, also remember which list it appears in. Then you can directly remove it from that list.

void MainMethod()
{
    var menulist = new List<Menu>(); // omitted: fill list
    
    // get the *full* list of items to remove, 
    // so you don't change a list that is still used in a foreach
    var todelete = ToDelete(menulist).ToList();

    // and remove them from their parent list
    foreach (var todo in todelete)
    {
        todo.list.Remove(todo.child);
    }
}

private IEnumerable<(List<Menu> list, Menu child)> ToDelete(List<Menu> menuitems)
{
    foreach (var item in menuitems)
    {
        if (item.IsDeleted)
        {
            // now we know that "item" must be removed from "menuitems"
            yield return (menuitems, item);
        }
        else
        {
            // if the parent is deleted, then all children will be gone as well
            //  - so only recursively check non-deleted items

            // pass the results of a recursive call up the call stack
            foreach (var pairs in ToDelete(item.Items))
            {
                yield return pairs;
            }
        }
    }
}
  • Related