2012-03-07 18 views
10

Ricevo un elenco di tipo di struttura en entity e voglio solo restituire i valori distinti dall'elenco. Sto usando il seguente approccio, tuttavia non è univoco l'elenco. Eventuali suggerimenti?Creazione di un elenco distinto di tipo personalizzato in C#

Param: List<Flag> flags

List<Flag> distinctFlags = flags.Distinct().ToList(); 

I valori di bandiera sono i seguenti: ID, Bandiera, FlagValue. Posso usare linq in questa istanza?

Grazie.

+0

Quali sono i tuoi valori di input e cosa vi aspettate come output? –

+0

Si trova all'interno o all'esterno di dbcontext? Mostra altro codice per favore. E se puoi, dai un esempio dei dati prima e dopo la trasformazione. –

+1

Raggruppali e scegli un vincitore. http://stackoverflow.com/questions/489258/linq-distinct-on-a-particular-property/491832#491832 –

risposta

14

Supponendo Flag è uno dei vostri modelli di entità, è possibile utilizzare un partialclass e sovrascrivere Equals e GetHashCode. Questo presuppone anche che tu abbia una proprietà Id sul tuo Flagclass che le identifica in modo univoco.

//this namespace MUST match the namespace of your entity model. 
namespace Your.Entity.Model.Namespace 
{ 
    public partial class Flag 
    { 
     public override bool Equals(object obj) 
     { 
      var item = obj as Flag; 

      if (item == null) 
      { 
       return false; 
      } 

      return this.Id.Equals(item.Id); 
     } 

     public override int GetHashCode() 
     { 
      return this.Id.GetHashCode(); 
     } 
    } 
} 

Uso sarebbe simile a questa

List<Flag> distinctFlags = allFlags.Distinct().ToList(); 
+1

Si dovrebbe anche implementare 'IEquatable ' sul tipo. – svick

+0

E probabilmente sovrascrivi '==' e '! =' –

+0

Hai solo bisogno di implementare 'Equals' e' GetHashCode'. Basta essere assolutamente sicuri che il valore del codice hash non cambi mai, il valore DEVE essere IMMUTABILE. – Enigmativity

1

Probabilmente flags è una lista di tipo di riferimento, e distinto non funziona come ci si aspetta! Questo perché Distinct() non funziona sul valore della bandiera nella lista, ma sui suoi riferimenti di memoria (che sono tutti diversi).

Devi scrivere una classe di confronto che insegna a Distinto come confrontare lo stesso flag. Supponiamo di avere questa classe bandiera:

public class flag 
{ 
    public string Name { get; set; } 
    public string Code { get; set; } 
} 

si dovrebbe creare una classe di confronto come questo:

class FlagComparer : IEqualityComparer<flag> 
{ 
    // Products are equal if their names and product numbers are equal. 
    public bool Equals(flag x, flag y) 
    { 

     //Check whether the compared objects reference the same data. 
     if (Object.ReferenceEquals(x, y)) return true; 

     //Check whether any of the compared objects is null. 
     if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
      return false; 

     //Check whether the products' properties are equal. 
     return x.Code == y.Code && x.Name == y.Name; 
    } 
} 

e la chiamata la sua dichiarazione:

List distinctFlags = flags.Distinct(new FlagComparer()).ToList(); 

In questo modo, metodo distinto sa esattamente come confrontare l'istanza della bandiera uguale.

UPDATE

Sulla base di tuo commento, se vuoi anche seguire il mio suggerimento, si dovrebbe scrivere la base di confronto come segue:

class FlagComparer : IEqualityComparer<flag> 
    { 
     // Products are equal if their names and product numbers are equal. 
     public bool Equals(flag x, flag y) 
     { 

      //Check whether the compared objects reference the same data. 
      if (Object.ReferenceEquals(x, y)) return true; 

      //Check whether any of the compared objects is null. 
      if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
       return false; 

      //Check whether the products' properties are equal. 
      return x.HostID == y.HostID && x.RuleID == y.RuleID && x.Flag == y.Flag && x.FlagValue == y.FlagValue; 
     } 
    } 

Naturalmente, ogni proprietà deve essere un tipo di valore .

dare uno sguardo qui per chiarire se stessi:

+1

Funzionerebbe, ma sovrascrivere 'Equals()' e implementare 'IEquatable ' è un approccio più comune, perché significa che non devi specificare il comparatore ogni volta. – svick

Problemi correlati