2012-11-21 22 views
44

Dodaję urządzenia zdalne do listy, ponieważ ogłaszają się w sieci. Chcę tylko dodać urządzenie do listy, jeśli nie zostało wcześniej dodane.Dodaj tylko unikatowy element do listy

Ogłoszenia nadchodzą przez odbiornik asynchroniczny gniazda, więc kod dodawania urządzenia może być uruchamiany na wielu wątkach. Nie jestem pewien, co robię źle, ale bez względu na to, co próbuję, kończę z duplikacjami. Oto, co aktualnie mam .....

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

Jaka jest definicja dla 'RemoteDevice'? – pstrjds

+0

dla celów debugowania, czy możesz przedłużyć swoją klasę _remoteDevices o pole znacznika czasu, _remoteDevices.lastSeen = teraz? – Beth

Odpowiedz

92

Jeśli wymagania są nie mieć duplikaty, należy używać do HashSet.

HashSet.Add powróci fałszywy gdy już istnieje element (jeśli jest, że nawet sprawy do Ciebie).

Można użyć konstruktora że @pstrjds linki poniżej (lub here), aby zdefiniować operator równości lub trzeba zaimplementować metody równości w RemoteDevice (GetHashCode & Equals).

+3

Chciał dodać tę odpowiedź. Możesz użyć tego przeciążenia, aby zdefiniować porównanie - http://msdn.microsoft.com/en-us/library/bb359100(v=vs.100).aspx – pstrjds

+4

Ważną informacją jest to, że HashSet nie ma gwarancji, że będzie respektować wstawienie zamówienie. Więc jeśli porządek jest ważny (elementy muszą pojawić się na liście w takiej samej kolejności, w jakiej je wstawiłeś, np. Co dzieje się z 'List '), to HashSet nie działa dobrze. – JulianR

+0

Wielkie dzięki za to. Czy nadal muszę zachować blokadę bezpieczeństwa wątku lub czy istnieje lepszy sposób? – Oli

5

Podobnie jak przyjęta odpowiedź mówi, że HashSet nie ma zamówienia. Jeśli zamówienie jest ważne, możesz nadal korzystać z Listy i sprawdzać, czy zawiera ona przedmiot przed dodaniem.

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

List.Contains sceniczne() na niestandardowej klasy/obiektu wymaga wykonania IEquatable<T> na niestandardowej klasy lub przesłanianie Equals. Dobrym pomysłem jest również wdrożenie GetHashCode w klasie. Jest za dokumentacji na 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

hi thx, ale co, jeśli nie można przesłonić, ponieważ używam odniesienia do czyjegoś kodu - co tu robisz? – 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);