Usuário com melhor resposta
[C#] Verificar itens antes de uma List

Pergunta
-
Bom dia galera, beleza? Tenho um ListBox e queria verificar itens antes de adicioná-los.
Classe para divisão de dados:
public class Info { public String Nome { get; set; } public decimal Valor { get; set; } public Info() { } public Info(string nome, decimal valor) { this.Nome = nome; this.Valor = valor; } }
Método para adicionar novo item:
List<Info> Produtos = new List<Info>(); Produtos.Add(new Info() { Nome = "Teste", Valor = 12 });
Método para pegar itens da List:
foreach (Info produto in Produtos) { MessageBox.Show(string.Format("Produto: {0}\n Valor: {1}", produto.Nome, produto.Valor)); }
Tentei verificar usando contains no PRODUTO dentro do foreach mas retonar sem valor. Como fazer isso?
- Editado Gerlanio Torres domingo, 19 de junho de 2016 14:22
Respostas
-
O "Contains" do List não vai achar porque você não tem o mesmo objeto para procurar.
O que o "Contains" faz é comparar a REFERÊNCIA do objeto (em caso de classes) para determinar se é a mesma. Então isso:
Info A = new Info("Nome 1", 10m); //esse tem a mesma REFERÊNCIA que "A" Info B = A; Info C = new Info("Nome 2", 20m); //veja que é igual a A //mas NÂO É "A", tem os mesmo valores, //mas não a mesma referência Info D = new Info("Nome 1", 10m); List<Info> Produtos = new List<Info>(); Produtos.Add(A); Produtos.Add(C); //Se você usar o "Contains(B)" vai retornar //positivo, pois B é igual a A. //No entanto "Contains(D)" vai retornar //negativo, pois D NÃO É "A", mesmo sendo //igual em suas propriedades
Como você pode ver aqui ReferenceSource, "Contains()" chama o método "Equals()" da classe. Toda classe derivada de object (ou seja, toda classe) usa o método do object para resolver o Equals, que é basicamente comparar a referência da classe. Se você rescrever esse método, poderá alterar essa decisão para comparar propriedades apenas. Outra alternativa é fazer um "foreach" você mesmo. O "Contains()" basicamente faz isso, um "foreach" e cada objeto rodando o método "Equals()" dele.
//Código do Contains (veja o link que pus anteriomente) public virtual bool Contains(Object item) { if (item==null) { for (int i = 0; i < _size; i++) if (_items[i]==null) return true; return false; } else { for(int i=0; i<_size; i++) if ((_items[i] != null) && (_items[i].Equals(item))) return true; return false; } } //Seu "foreach" public bool Contains(List<Info> Produtos, Info Item) { if (Item == null) { //Faça o mesmo? Ou não pode ser null nunca ... //Ai você decide } foreach (Info Existing in Produtos) if (Existing.Nome == Item.Nome && Existing.Valor == Existing.Valor) return true; //Era para comparar o valor também ou só o nome? return false; }
Entendeu o exemplo?
- Sugerido como Resposta SammuelMiranda segunda-feira, 20 de junho de 2016 12:14
- Marcado como Resposta Thales F Quintas segunda-feira, 20 de junho de 2016 13:39
Todas as Respostas
-
-
O "Contains" do List não vai achar porque você não tem o mesmo objeto para procurar.
O que o "Contains" faz é comparar a REFERÊNCIA do objeto (em caso de classes) para determinar se é a mesma. Então isso:
Info A = new Info("Nome 1", 10m); //esse tem a mesma REFERÊNCIA que "A" Info B = A; Info C = new Info("Nome 2", 20m); //veja que é igual a A //mas NÂO É "A", tem os mesmo valores, //mas não a mesma referência Info D = new Info("Nome 1", 10m); List<Info> Produtos = new List<Info>(); Produtos.Add(A); Produtos.Add(C); //Se você usar o "Contains(B)" vai retornar //positivo, pois B é igual a A. //No entanto "Contains(D)" vai retornar //negativo, pois D NÃO É "A", mesmo sendo //igual em suas propriedades
Como você pode ver aqui ReferenceSource, "Contains()" chama o método "Equals()" da classe. Toda classe derivada de object (ou seja, toda classe) usa o método do object para resolver o Equals, que é basicamente comparar a referência da classe. Se você rescrever esse método, poderá alterar essa decisão para comparar propriedades apenas. Outra alternativa é fazer um "foreach" você mesmo. O "Contains()" basicamente faz isso, um "foreach" e cada objeto rodando o método "Equals()" dele.
//Código do Contains (veja o link que pus anteriomente) public virtual bool Contains(Object item) { if (item==null) { for (int i = 0; i < _size; i++) if (_items[i]==null) return true; return false; } else { for(int i=0; i<_size; i++) if ((_items[i] != null) && (_items[i].Equals(item))) return true; return false; } } //Seu "foreach" public bool Contains(List<Info> Produtos, Info Item) { if (Item == null) { //Faça o mesmo? Ou não pode ser null nunca ... //Ai você decide } foreach (Info Existing in Produtos) if (Existing.Nome == Item.Nome && Existing.Valor == Existing.Valor) return true; //Era para comparar o valor também ou só o nome? return false; }
Entendeu o exemplo?
- Sugerido como Resposta SammuelMiranda segunda-feira, 20 de junho de 2016 12:14
- Marcado como Resposta Thales F Quintas segunda-feira, 20 de junho de 2016 13:39
-
-
Verificar os itens já adicionados na list para não pode adicionar dois do mesmo. Preciso apenas só verificar o nome, o valor não me interessa. Hehe
- Editado Gerlanio Torres segunda-feira, 20 de junho de 2016 12:35
-
Então substitua isso:
public bool Contains(List<Info> Produtos, Info Item) { if (Item == null) { //Faça o mesmo? Ou não pode ser null nunca ... //Ai você decide } foreach (Info Existing in Produtos) if (Existing.Nome == Item.Nome && Existing.Valor == Existing.Valor) return true; //Era para comparar o valor também ou só o nome? return false; }
Por isso:
public bool Contains(List<Info> Produtos, Info Item) { foreach (Info Existing in Produtos) if (Existing.Nome == Item.Nome) return true; return false; }
A parte do "Item == null" é para você tratar se o item for nulo o que fazer.