104 votes

Ajouter uniquement un élément unique à la liste

J'ajoute des appareils distants à une liste lorsqu'ils s'annoncent sur le réseau. Je ne veux ajouter le périphérique à la liste que s'il n'a pas été ajouté précédemment.

Les annonces sont transmises par un écouteur de socket asynchrone, de sorte que le code d'ajout d'un périphérique peut être exécuté sur plusieurs threads. Je ne suis pas sûr de ce que je fais mal, mais peu importe ce que j'essaie, je me retrouve avec des doublons. Voici ce que j'ai actuellement : .....

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);
     }
}

174voto

Austin Salonen Points 28057

Si vos exigences sont de ne pas avoir de doublons, vous devriez utiliser un fichier HashSet .

HashSet.Add retournera faux lorsque l'élément existe déjà (si cela vous importe).

Vous pouvez utiliser le constructeur dont @pstrjds fait le lien ci-dessous (ou aquí ) pour définir l'opérateur d'égalité, ou vous devrez implémenter les méthodes d'égalité dans le module RemoteDevice ( GetHashCode & Equals ).

29voto

//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);

19voto

Luke Eckley Points 320

Tout comme la réponse acceptée dit qu'un HashSet n'a pas d'ordre. Si l'ordre est important, vous pouvez continuer à utiliser une liste et vérifier si elle contient l'élément avant de l'ajouter.

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

Pour exécuter List.Contains() sur une classe ou un objet personnalisé, il faut implémenter IEquatable<T> sur la classe personnalisée ou en surchargeant l'option Equals . C'est une bonne idée de mettre également en œuvre GetHashCode dans la classe également. Ceci est conforme à la documentation à l'adresse 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;
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X