
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 i = 1; i <= qtd; i++)
{
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?