Brincando com List<T> - como evitar adição de conteúdo duplicado

Estava aqui no note brincando um pouco, enquanto esperava o horário do webcast, e tive uma idéia (boba, mas legalzinha): por que não criar uma coleção genérica que não aceite repetidos, como no java temos as classes derivadas da interface Set?

Então, vamos lá. O que eu preciso?

Criar uma classe que herde de List<T> (uma lista genérica) e que sobreponha o método Add(object item), que é o único que vou usar no meu programinha. Poderia criar uma classe que herde de um monte de interfaces, mas aí eu teria que implementar diversos métodos - NEM!!!

Primeiro devo ver se a classe não é sealed (aí ela não pode ser estendida). Não é: isso é bom porque posso herdar dela.

Segundo, devo descobrir se o método Add(object item) foi preparado para sobreposição usando virtual. Não foi: isso fará minha classe se comportar de modo diferente do esperado se eu usar polimorfismo - mas não vai ser o caso.

Então criei a classe:

class ListaUnica<T> : List<T>
{
    
public new void Add(T item)
    {
        
if (!this.Contains(item))
            
base.Add(item);
    
}
}

Para testar a classe e ter uma idéia da performance, fiz o programa abaixo:

class Program
{
    
static void Main(string[] args)
    {
        ListaUnica<String> lista 
= new ListaUnica<string>();
        
DateTime inicio DateTime.Now;
        int 
qtd 100000;

        for 
(int 1i <qtdi++)
        {
            lista.Add(
new Random(i).Next(1, qtd + 1).ToString());

            if 
(i % 100 == 0)
            {
                Console.Clear()
;
                
Console.WriteLine("completo: {0:n1} %", i * 100f / qtd);
                
Console.WriteLine("quantidade de elementos da lista: {0}", lista.Count());
            
}
        }

        DateTime fim 
DateTime.Now;

        
Console.WriteLine("início: {0}", inicio.ToString("dd/MM/yyyy HH:mm:ss.fff"));
        
Console.WriteLine("fim...: {0}", fim.ToString("dd/MM/yyyy HH:mm:ss.fff"));
        
Console.WriteLine("tempo.: {0}", fim - inicio);

        
//com seed no Random -> Random(i)
        //completo: 100,0 %
        //quantidade de elementos da lista: 88719
        //início: 18/01/2010 01:07:42.140
        //fim...: 18/01/2010 01:09:44.265
        //tempo.: 00:02:02.1250000

        //sem seed no Random -> Random()
        //completo: 100,0 %
        //quantidade de elementos da lista: 85
        //início: 18/01/2010 01:10:39.953
        //fim...: 18/01/2010 01:10:41.265
        //tempo.: 00:00:01.3125000

        //dois minutos para inserir 88719 elementos (e conferir se o novo existia)
        //um segundo para inserir 85 elementos (mesmo caso)
        
Console.ReadKey();
    
}
}

E não é que funciona?

Comentários (7) -

Camila Neiva
Camila Neiva
19/01/2010 09:07:52 #

Agnaldo! bom dia!

Só uma dúvida... neste caso, não temos nenhuma melhora de performance por usar uma classe, né? poderíamos simplesmente ter usado o if dentro do for e o resultado e desempenho seria o mesmo, certo?
Pergunto pq geralmente é o que faço...

agnaldo
agnaldo
19/01/2010 13:10:06 #

E se vc usa essa lógica em 23043404 locais no código???

Aí é mais vantagem fazer na List... só por conta de manutenção...

O desempenho é igual... olhando por cima, sem fazer testes, não vejo nada de ganho...

Felipe Aron
Felipe Aron
21/01/2010 11:25:51 #

Eu vejo da seguinte forma:

Isso é um encapsulamento de regra. Essa classe se torna viável caso eu queira usar listas no meu projeto que não permita duplicações. Ai é vantagem pois a regra está centrada num único lugar !! Precisou alterar algo na regra - Muda um local que será visualizado por todo o resto. Laughing

Agora se essa utilização é uma excessão (irei utilizar em apenas um lugar por exemplo) ai podemos usar o IF diretamente.

Em termos de desempenho é a mesma coisa. Porém a forma como usar é relativa. Laughing

agnaldo
agnaldo
22/01/2010 07:32:33 #

Perfeito.

Israel Aece
Israel Aece
10/02/2010 15:30:01 #

Boas,

Use o HashSet<T>, que já tem essa finalidade.

agnaldo
agnaldo
12/02/2010 09:57:06 #

opa... blz??? por isso o post é Brincando com List<T>...

abração procê...

Daniel Cobalto
Daniel Cobalto
01/07/2010 11:11:29 #

Esse processo funciona OK com os tipos básicos, mas e se a minha lista trabalhar com objetos?

Comentar

  Country flag

biuquote
  • Comentário
  • Pré-visualização
Loading