2012-11-21 9 views
44

Aggiungo dispositivi remoti a un elenco mentre si annunciano attraverso la rete. Voglio solo aggiungere il dispositivo all'elenco se non è stato aggiunto in precedenza.Aggiungi solo un articolo univoco all'elenco

Gli annunci stanno arrivando attraverso un listener di socket asincrono in modo che il codice per aggiungere un dispositivo possa essere eseguito su più thread. Non sono sicuro di cosa sto sbagliando, ma non importa cosa cerco, finisco con le duplicazioni. Ecco quello che ho attualmente .....

lock (_remoteDevicesLock) 
{ 
    RemoteDevice rDevice = (from d in _remoteDevices 
          where d.UUID.Trim().Equals(notifyMessage.UUID.Trim(), StringComparison.OrdinalIgnoreCase) 
          select d).FirstOrDefault(); 
    if (rDevice != null) 
    { 
     //Update Device..... 
    } 
    else 
    { 
     //Create A New Remote Device 
     rDevice = new RemoteDevice(notifyMessage.UUID); 
     _remoteDevices.Add(rDevice); 
    } 
} 
+0

Qual è la definizione di 'RemoteDevice'? – pstrjds

+0

per scopi di debug, puoi estendere la tua classe _remoteDevices con un campo data/ora, _remoteDevices.lastSeen = now? – Beth

risposta

92

Se i requisiti sono avere duplicati, si dovrebbe utilizzare un HashSet.

HashSet.Add restituirà false quando l'elemento esiste già (se ciò è importante anche per voi).

È possibile utilizzare il costruttore che @pstrjds collegamenti al di sotto (o here) per definire l'operatore di uguaglianza o avrete bisogno di implementare i metodi di uguaglianza in RemoteDevice (GetHashCode & Equals).

+3

Stava per aggiungere questa risposta. È possibile utilizzare questo overload per definire il confronto: http://msdn.microsoft.com/en-us/library/bb359100(v=vs.100).aspx – pstrjds

+4

Una nota importante qui è che HashSet non è garantito il rispetto dell'inserimento ordine. Quindi se l'ordine è importante (gli articoli devono apparire nella lista nello stesso ordine in cui li hai inseriti, come succede con 'Lista ') allora HashSet non funziona bene. – JulianR

+0

Mille grazie per questo. Devo ancora mantenere il blocco per sicurezza del filo o c'è un modo migliore? – Oli

5

Proprio come la risposta accettata dice che un HashSet non ha un ordine. Se l'ordine è importante, puoi continuare a utilizzare un elenco e controllare se contiene l'elemento prima di aggiungerlo.

if (_remoteDevices.Contains(rDevice)) 
    _remoteDevices.Add(rDevice); 

List.Contains dello spettacolo() su una classe personalizzata/oggetto richiede attuazione IEquatable<T> sulla classe personalizzata o sovrascrivendo il Equals. È una buona idea anche implementare GetHashCode nella classe. Questo è per la documentazione in https://msdn.microsoft.com/en-us/library/ms224763.aspx

public class RemoteDevice: IEquatable<RemoteDevice> 
{ 
    private readonly int id; 
    public RemoteDevice(int uuid) 
    { 
     id = id 
    } 
    public int GetId 
    { 
     get { return id; } 
    } 

    // ... 

    public bool Equals(RemoteDevice other) 
    { 
     if (this.GetId == other.GetId) 
      return true; 
     else 
      return false; 
    } 
    public override int GetHashCode() 
    { 
     return id; 
    } 
} 
+0

ciao ma cosa succede se non è possibile eseguire l'override perché sto usando un riferimento al codice di qualcun altro - cosa si fa qui? – BKSpurgeon

8
//HashSet allows only the unique values to the list 
HashSet<int> uniqueList = new HashSet<int>(); 

var a = uniqueList.Add(1); 
var b = uniqueList.Add(2); 
var c = uniqueList.Add(3); 
var d = uniqueList.Add(2); // should not be added to the list but will not crash the app 

//Dictionary allows only the unique Keys to the list, Values can be repeated 
Dictionary<int, string> dict = new Dictionary<int, string>(); 

dict.Add(1,"Happy"); 
dict.Add(2, "Smile"); 
dict.Add(3, "Happy"); 
dict.Add(2, "Sad"); // should be failed // Run time error "An item with the same key has already been added." App will crash 

//Dictionary allows only the unique Keys to the list, Values can be repeated 
Dictionary<string, int> dictRev = new Dictionary<string, int>(); 

dictRev.Add("Happy", 1); 
dictRev.Add("Smile", 2); 
dictRev.Add("Happy", 3); // should be failed // Run time error "An item with the same key has already been added." App will crash 
dictRev.Add("Sad", 2);