如何在C#字典中获得免费条目

时间:2009-06-29 13:06:24

标签: c# dictionary

我正在运行服务器,我希望有一个用户词典,并为每个用户提供一个特定的号码。

Dictionary<int,ServerSideUser> users = new Dictionary<int,ServerSideUser>();

密钥代表服务器上的用户,因此当人们向该用户发送消息时,他们会将消息发送给该号码。我不妨使用用户的IP号码,但这不是一个好主意。

我需要为每个用户分配这样一个号码,我真的不知道该怎么做。有人建议像

Enumerable.Range(int.MinValue, int.MaxValue)
.Except(users.Select(x => x.Key)).First();

但我真的不认为这是最佳方式。 另外,我在其他地方的List(或LinkedList)也有同样的问题。

有什么想法吗?

9 个答案:

答案 0 :(得分:9)

如果“数字”的大小无关紧要,请选择Guid,它将始终是唯一且不可猜测的。

答案 1 :(得分:3)

如果你想要一个使用任意有序整数键的字典,你也可以使用List<ServerSideUser>,其中列表索引用作键。

是否有特定原因需要使用Dictionary

使用List<>或类似的数据结构肯定有局限性。由于并发问题,您根本不想从列表中删除用户,除非在循环服务器时。否则,您可能会遇到这样的情况:用户255向用户1024发送消息,用户1024断开连接并被新用户1024替换。新用户1024然后接收针对旧用户1024的消息。

如果您希望能够管理用户列表的内存占用,那么许多其他方法都可以使用;如果您想使用ints而不是GuidsWill's answer会特别好。

答案 2 :(得分:1)

为什么不跟踪当前的最大数量,并在每次添加新用户时将该数字增加一个?

答案 3 :(得分:1)

另一个选项:使用工厂生成ServerSideUser实例,为每个用户分配一个新的唯一ID。

在此示例中,工厂本身就是类。您无法实例化该类,您必须通过调用该类型上的静态Create方法来获取新实例。它递增ID生成器并使用此新id创建新实例。有许多方法以线程安全的方式执行此操作,我在这里以一种基本的1.1兼容方式(可能实际编译的c#伪代码)执行此操作:

public class ServerSideUser
{
  // user Id
  public Id {get;private set;}
  // private constructor
  private ServerSideUser(){}
  private ServerSideUser(int id) { Id = id; }

  // lock object for generating an id
  private static object _idgenLock = new Object();
  private static int _currentId = 0; // or whatever
  // retrieves the next id; thread safe 
  private static int CurrentId
  {
    get{ lock(_idgenLock){ _currentId += 1; return _currentId; } }
  }  

  public static ServerSideUser Create()
  {
    return new ServerSideUser(CurrentId);
  }
}

答案 4 :(得分:1)

我建议你的方法和增量的结合。

由于您的数据在内存中,因此使用int类型的标识符就足够了。 为下一个用户和免费标识符的链接列表创建一个变量。

添加新用户后,请使用列表中的ID。如果列表为空 - 使用变量并递增它。

删除用户后,将其标识符添加到词典中。

P.S。考虑使用数据库。

答案 5 :(得分:1)

首先,我还首先考虑GUID建议。其次,我假设你以某种方式在服务器上持久保存用户信息,并且这可能是一个数据库。如果是这种情况,为什么不让数据库通过主键为每个用户选择一个唯一的ID?也许这不是你在这里尝试做的最好的选择,但这是数据库多年来一直处理的问题,那么,为什么要重新发明呢?

答案 6 :(得分:0)

我认为这取决于您如何定义客户的“唯一性”。

例如,如果您在同一台计算机上有两个不同的客户端,您认为它们是两个客户端还是一个?

我建议您使用long值表示连接建立的时间,如“hhmmss”,甚至可以包含毫秒

答案 7 :(得分:0)

为什么不从1开始向上计数?

lock(dict) {
   int newId = dict.Count + 1;
   dict[newId] = new User();
}

如果您真的担心一半的世界人口出现在您的服务器上,请尝试使用long:s而不是...... :-D

答案 8 :(得分:0)

也许有点野蛮,但DateTime.Now.Ticks可能适合你吗?作为额外的奖励,您知道用户何时被添加到您的词典中。

来自关于Ticks的MSDN文档...

  

单个刻度表示一百纳秒或一百万分之一   第二。一毫秒内有10,000个滴答。

     

此属性的值表示100纳秒间隔的数量   已经过了自0001年1月1日午夜12:00:00起   表示DateTime .. ::。MinValue。