2014-08-13 16 views
6

Qualcuno può spiegare perché questi due metodi restituiscono valori diversi?C# contiene il comportamento

List<CustomerSummary> summaries = new List<CustomerSummary>(); 

for (var i = 0; i < 10; i++) 
{ 

var summary = new CustomerSummary() { ID = 1, Name = "foo", balance = 50.00 }; 

if (!summaries.Contains(summary)) 
    summaries.Add(summary); 

} 

-

List<CustomerSummary> summaries = new List<CustomerSummary>(); 

for (var i = 0; i < 10; i++) 
{ 

var summary = new CustomerSummary() { ID = 1, Name = "foo", balance = 50.00 }; 

if (!summaries.Any(s=> s.ID == summary.ID)) 
    summaries.Add(summary); 

} 

Il primo metodo ha 10 elementi nella lista, mentre il secondo ha 1. Perché la prima (contiene()) Metodo mai valutare come vero?

Quello che sto cercando di chiedere è perché sono 2 oggetti dello stesso tipo con gli stessi valori per ogni proprietà che non valuta come equivalente (nel primo metodo)?

risposta

3

tuo primo blocco di codice crea una nuova istanza all'interno del ciclo, e quindi immediatamente controllando se l'istanza esatta è già nella collezione. Non può essere - l'hai appena creato.

Si potrebbe anche scrivere in questo modo:

List<CustomerSummary> summaries = new List<CustomerSummary>(); 

for (var i = 0; i < 10; i++) 
{ 
    var summary = new CustomerSummary { ID = 1, Name = "foo", balance = 50.00 }; 

    summaries.Add(summary); 
} 

tuo secondo blocco di codice è il controllo per l'esistenza di qualsiasi elemento della collezione con un ID di corrispondenza. Dal momento che hai codificato l'ID in modo che sia 1, stai per aggiungere un oggetto solo la prima volta. Ogni istanza creata dopo restituirà false nell'istruzione if e non verrà aggiunta.

Si potrebbe modificare l'azione modificando l'ID:

for (var i = 0; i < 10; i++) 
{ 
    var summary = new CustomerSummary { ID = i, Name = "foo", balance = 50.00 }; 

    if (!summaries.Any(s=> s.ID == summary.ID)) 
     summaries.Add(summary); 
} 

Anche in questo caso, la dichiarazione if non è più nemmeno necessario, poiché si conosce l'ID non possono assolutamente essere già presente nella collezione, così da poter basta rimuovere il segno di spunta.

+0

Forse questa è la parte che non capisco - l'istanza. Perché 2 oggetti dello stesso tipo hanno gli stessi valori per ogni proprietà che non valuta come equivalente? – user2865446

+1

Questo è solo il modo in cui funziona, per impostazione predefinita. Hai una raccolta di istanze di 'CustomerSummary', e poi crei una nuova istanza' CustomerSummary'. Quando esegui il confronto 'Contains()', stai davvero confrontando il riferimento della tua nuova _instance_ con i riferimenti di tutte le istanze precedenti già presenti nella raccolta ... non stai confrontando i valori di tutte le singole proprietà a vicenda. –

+1

Tuttavia, puoi _can_ implementare l'interfaccia ['IEqualityComparer'] (http://stackoverflow.com/questions/6694508/how-to-use-the-iequalitycomparer) sulla tua classe' CustomerSummary' (fai una ricerca e trovare buoni tutorial). Fondamentalmente, se implementato correttamente, specifica come confrontare due istanze di un oggetto. Ad esempio, è possibile definire esplicitamente che due istanze di 'CustomerSummary' sono uguali quando i loro valori di' ID' sono uguali. –

2

Questo perché Contains() corrisponde al riferimento dello Summary .. e non allo ID.

ogni volta che fate un

var summary = new CustomerSummary() { ID = 1, Name = "foo", balance = 50.00 }; 

nel vostro ciclo, si crea una nuova istanza di CustomerSummary e, quindi, un nuovo riferimento viene memorizzato in summary, pensavate che i valori di ogni proprietà all'interno della CustomerSummary ASRE esattamente lo stesso. .

0
if (!summaries.Contains(summary)) 

Questo controllerà tutta touple (riga)

{ ID = 1, Name = "foo", balance = 50.00 } 

E

Questo controllerà singolo elemento Id=1.

1

hi nella prima funzione che si cercando di utilizzare contiene in tutto l'oggetto e non sulla proprietà come si fa in seconda funzione provare cambiare prima come questo

List<CustomerSummary> summaries = new List<CustomerSummary>(); 

     for (var i = 0; i < 10; i++) 
     { 

      var summary = new CustomerSummary() { ID = 1, Name = "foo", balance = 50.00 }; 

      if (!summaries.Select(s=>s.ID).Contains(summary.ID)) 
       summaries.Add(summary); 

     } 
2

List<T>.Contains metodo determina l'uguaglianza utilizzando il comparatore di uguaglianza predefinito. E qui stai cercando di confrontare due oggetti diversi. Entrambi possono avere tutte le proprietà riempite con valori corrispondenti, ma questi sono due oggetti diversi.Se si desidera utilizzare realmente il metodo Contiene qui, è necessario implementare il metodo IEquatable<T>.Equals nell'oggetto CustomerSummary.