2013-02-22 32 views
5

Ho una lista che contiene oggetti ma questi oggetti non sono univoci nella lista. Ho wrte questo codice per rendere unico loro in un altro elenco:List.Contains non funziona correttamente

foreach (CategoryProductsResult categoryProductsResult in categoryProductsResults.Where(categoryProductsResult => !resultSet.Contains(categoryProductsResult))) 
{ 
    resultSet.Add(categoryProductsResult); 
} 

Ma alla resultSet finale è lo stesso con categoryProductsResults. seconda fila

di categoryProductsResult:

enter image description here

resultSet prima fila:

enter image description here

Come si può vedere prima fila di resultSet e seconda fila di categoryProductsResult è lo stesso, ma si aggiunge la seconda fila per ottenere set.

Avete qualche suggerimento?

+1

Mostraci dove si esegue l'override di '.equals()'. –

risposta

12

Contains utilizza il comparatore predefinito che confronta i riferimenti poiché la classe non sovrascrive Equals e GetHashCode.

class CategoryProductsResult 
{ 
    public string Name { get; set; } 
    // ... 

    public override bool Equals(object obj) 
    { 
     if(obj == null)return false; 
     CategoryProductsResult other = obj as CategoryProductsResult; 
     if(other == null)return false; 
     return other.Name == this.Name; 
    } 

    public override int GetHashCode() 
    { 
     return Name.GetHashCode(); 
    } 
} 

Ora si può semplicemente utilizzare:

resultSet = categoryProductsResults.Distinct().ToList(); 
+1

Codice eccellente, grazie mille. – cagin

0

Gli oggetti di riferimento in un elenco sono indicizzati dal loro codice hash. Così, Contains troverete mai un oggetto di riferimento con lo stesso codice hash (a meno che non si ignora l'attuazione GetHashCode e Equals nella classe.

Questo SO answer spiega.

3

List utilizza l'operatore di confronto restituito da EqualityComparer.Default e secondo alla documentazione per questo:

la proprietà di default controlla se tipo T implementa il System.IEquatable (Of T) l'interfaccia e, in caso affermativo, restituisce un EqualityComparer (Of T) che utilizza tale implementazione. In caso contrario, restituisce un EqualityComparer (Of T) che utilizza le sostituzioni di Object.Equals e Object.GetHashCode forniti da T.

Quindi è possibile implementare IEquatable sulla vostra classe personalizzata, o ignorare le Equals (e GetHashCode) metodi per fare il confronto con le proprietà richieste. In alternativa, è possibile utilizzare linq:

bool contiene = list.Any (i => i.Id == obj.Id);

0

è necessario controllare se il vostro elemento corrente è contenuta nella vostra lista di destinazione per ogni iterazione. Attualmente controlli una volta all'inizio del ciclo, il che significa che nessuno dei tuoi articoli è nella lista di destinazione.

Penso che Distinct stia già facendo quello che vuoi, potresti voler usare questa estensione invece del tuo loop.

1

Ogni categoryProductsResult è diverso l'uno dall'altro. È come qualcosa che puoi vedere here.Se vuoi uno più semplice e ProductId è il tuo identificatore univoco. Basta fare il codice qui sotto:

foreach (CategoryProductsResult categoryProductsResult in categoryProductsResults.Where(categoryProductsResult => resultSet.ProductId !=categoryProductsResult.ProductId) 
{ 
    resultSet.Add(categoryProductsResult); 
} 
Problemi correlati