Подтвердить что ты не робот

Добавить только элемент в список

Я добавляю удаленные устройства в список, когда они объявляют себя по сети. Я просто хочу добавить устройство в список, если он ранее не был добавлен.

Объявления поступают через прослушиватель асинхронного сокета, поэтому код для добавления устройства может выполняться на нескольких потоках. Я не уверен, что я делаю неправильно, но не матер, что я пытаюсь. Я получаю дубликаты. Вот что я сейчас имею.

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

Ответ 1

Если ваши требования не имеют дубликатов, вы должны использовать HashSet.

HashSet.Add вернет false, когда элемент уже существует (если это даже имеет значение для вас).

Вы можете использовать конструктор, который ссылается на @pstrjds ниже (или здесь), чтобы определить оператор равенства, или вам нужно реализовать методы равенства в RemoteDevice (GetHashCode и Equals).

Ответ 2

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

Ответ 3

Как и в принятом ответе, у HashSet нет порядка. Если порядок важен, вы можете продолжить использовать список и проверить, содержит ли он элемент перед его добавлением.

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

Выполнение List.Contains() для пользовательского класса/объекта требует реализации IEquatable<T> в пользовательском классе или переопределения Equals. Также неплохо также реализовать GetHashCode в классе. Это соответствует документации 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;
    }
}