【问题标题】:Only Add Unique Item To List仅将唯一项目添加到列表
【发布时间】:2012-11-09 23:46:14
【问题描述】:

我正在将远程设备添加到列表中,因为它们通过网络宣布自己。如果之前没有添加过,我只想将设备添加到列表中。

通知来自异步套接字侦听器,因此添加设备的代码可以在多个线程上运行。我不确定我做错了什么,但无论我尝试什么,最终都会出现重复。这是我目前拥有的.....

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

【问题讨论】:

  • RemoteDevice的定义是什么?
  • 出于调试目的,您能否使用时间戳字段 _remoteDevices.lastSeen = now 扩展您的 _remoteDevices 类?

标签: c# .net c#-4.0


【解决方案1】:

如果您的要求是没有重复,您应该使用HashSet

当项目已经存在时,

HashSet.Add 将返回 false(如果这对您来说很重要的话)。

您可以使用@pstrjds 链接到下面的构造函数(或here)来定义相等运算符,或者您需要在RemoteDeviceGetHashCodeEquals)中实现相等方法。

【讨论】:

  • 正要添加这个答案。您可以使用此重载来定义比较 - msdn.microsoft.com/en-us/library/bb359100(v=vs.100).aspx
  • 这里的一个重要说明是 HashSet 不能保证遵守插入顺序。因此,如果顺序很重要(项目需要以与您放入的顺序相同的顺序出现在列表中,例如 List<T> 发生的情况),那么 HashSet 就不能正常工作。
  • 非常感谢。为了线程安全,我还需要保留锁还是有更好的方法?
  • @Oli 你需要保留锁,但是操作会快很多,所以他们不会互相等待。不幸的是,没有ConcurrentSet 课程。但是有一个 ConcurrentDictionary 类,因此您可以使用它,将您的值存储为键,然后将 null 存储在值中。
  • @Oli:如果我是你,我会发布另一个问题来解决这个问题(包括 GetHashCode 和 Equals 的完整来源,以及当你不希望它们匹配时它们匹配的情况)。
【解决方案2】:

就像接受的答案说 HashSet 没有订单一样。如果顺序很重要,您可以继续使用 List 并在添加之前检查它是否包含该项目。

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

【讨论】:

  • 嗨,谢谢,但是如果你不能覆盖,因为我使用的是对其他人的代码的引用 - 在这里做什么?
【解决方案3】:
//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);

【讨论】:

    猜你喜欢
    • 2016-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-24
    • 1970-01-01
    • 2020-06-23
    • 2019-11-29
    • 2017-09-19
    相关资源
    最近更新 更多