2011-03-01 11 views
71

¿Hay alguna colección en C# que no le permita agregarle elementos duplicados? Por ejemplo, con la clase de tonto¿Colección que solo permite elementos únicos en .NET?

public class Customer { 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string Address { get; set; } 

    public override int GetHashCode() { 
     return (FirstName + LastName + Address).GetHashCode(); 
    } 

    public override bool Equals(object obj) { 
     Customer C = obj as Customer; 
     return C != null && String.Equals(this.FirstName, C.FirstName) && String.Equals(this.LastName, C.LastName) && String.Equals(this.Address, C.Address); 
    } 
} 

El siguiente código (obviamente) una excepción:

Customer Adam = new Customer { Address = "A", FirstName = "Adam", LastName = "" }; 
Customer AdamDup = new Customer { Address = "A", FirstName = "Adam", LastName = "" }; 

Dictionary<Customer, bool> CustomerHash = new Dictionary<Customer, bool>(); 
CustomerHash.Add(Adam, true); 
CustomerHash.Add(AdamDup, true); 

¿Pero hay una clase que de igual forma se garantizar la unicidad, pero sin KeyValuePairs? Pensé que HashSet<T> haría eso, pero después de leer los documentos parece que la clase es solo una implementación establecida (vaya figura).

+3

No entiendo su problema con 'HashSet '. MSDN dice "La clase HashSet proporciona operaciones de conjunto de alto rendimiento. Un conjunto es una colección que no contiene elementos duplicados y cuyos elementos no están en un orden particular". –

+4

¿Puede explicar más por qué 'HashSet ' no es suficiente? – JaredPar

+0

@mootinator: La clase 'Dictionary ' no * garantiza ningún tipo de orden. – LukeH

Respuesta

147

HashSet<T> es lo que estás buscando. De MSDN (énfasis añadido):

El HashSet<T> clase proporciona operaciones de conjuntos de alto rendimiento. Un conjunto es una colección que no contiene elementos duplicados, y cuyos elementos no están en ningún orden particular.

Tenga en cuenta que la HashSet<T>.Add(T item) method devuelve un bool - true si el artículo se añadió a la colección; false si el artículo ya estaba presente.

10

Desde la página HashSet<T> en MSDN:

El HashSet (Of T) clase proporciona operaciones de conjuntos de alto rendimiento. Un conjunto es una colección que no contiene elementos duplicados, y cuyos elementos no están en un orden particular.

(el énfasis es mío)

4

Usted puede intentar HashSet<T>

+2

http://meta.stackoverflow.com/tags/link-only-answers/info –

3

Si todo lo que necesita es garantizar la exclusividad de los elementos, entonces HashSet es lo que necesita.

¿Qué quiere decir cuando dice "solo una implementación de conjunto"? Un conjunto es (por definición) una colección de elementos únicos que no guarda el orden de los elementos.

+0

Tiene toda la razón; la pregunta fue algo estúpida. Básicamente, estaba buscando algo que arrojara una excepción cuando se agregaba un duplicado (como Dictionary ), pero como ya se mencionó, HashSet devuelve falso en un complemento duplicado. +1, gracias. –

1

Sólo para añadir mis 2 centavos ...

si necesita un ValueExistingException de lanzamiento de HashSet<T> también puede crear fácilmente su colección:

public class ThrowingHashSet<T> : ICollection<T> 
{ 
    private HashSet<T> innerHash = new HashSet<T>(); 

    public void Add(T item) 
    { 
     if (!innerHash.Add(item)) 
      throw new ValueExistingException(); 
    } 

    public void Clear() 
    { 
     innerHash.Clear(); 
    } 

    public bool Contains(T item) 
    { 
     return innerHash.Contains(item); 
    } 

    public void CopyTo(T[] array, int arrayIndex) 
    { 
     innerHash.CopyTo(array, arrayIndex); 
    } 

    public int Count 
    { 
     get { return innerHash.Count; } 
    } 

    public bool IsReadOnly 
    { 
     get { return false; } 
    } 

    public bool Remove(T item) 
    { 
     return innerHash.Remove(item); 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     return innerHash.GetEnumerator(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return this.GetEnumerator(); 
    } 
} 

Esto puede ser útil, por ejemplo, si la necesita en muchos lugares ...

+0

Claro. Me preguntaba si algo estaba incorporado, pero gracias +1 –

16

¿Qué tal solo un método de extensión en HashSet?

public static void AddOrThrow<T>(this HashSet<T> hash, T item) 
{ 
    if (!hash.Add(item)) 
     throw new ValueExistingException(); 
} 
Cuestiones relacionadas