Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 字典列表与嵌套字典_C#_List_Dictionary - Fatal编程技术网

C# 字典列表与嵌套字典

C# 字典列表与嵌套字典,c#,list,dictionary,C#,List,Dictionary,为了稍微解释一下我的环境,我需要跟踪用户和每个用户拥有的东西的集合。这是高度动态的,尽管基本用户的数量总是高于他们拥有的东西的集合。我决定这样做: private static Dictionary<string, Dictionary<string, MyClass>> ActiveUsers = new Dictionary<string, Dictionary<string, MyClass>>(); private static

为了稍微解释一下我的环境,我需要跟踪用户和每个用户拥有的东西的集合。这是高度动态的,尽管基本用户的数量总是高于他们拥有的东西的集合。我决定这样做:

private static Dictionary<string, Dictionary<string, MyClass>> ActiveUsers = 
    new Dictionary<string, Dictionary<string, MyClass>>();
private static ConcurrentDictionary<string, ActiveUser> ActiveUsers { get; set; }

private class ActiveUser {
   public int ConnectionId { get; set; }
   public Dictionary<string, MyClass> MyClasses { get; set; } = new Dictionary<string, MyClass>();
}   
// . . . 
Dictionary<string, ActiveUser> ActiveUsers = new Dictionary<string, ActiveUser>();
如果有帮助,ActiveUsers是ASP.NET控制器中的一个静态字段

编辑:回答评论

本词典的使用方式如下:

public static MyClass GetInformation(string myId, string objectId)
{
    //Validation removed
    Dictionary<string, MyClass> dictionaryResult = null;
    MyClass result = null;

    if (!ActiveUsers.TryGetValue(myId, out dictionaryResult)) //check if the user was already added to the Dictionary
    {
        dictionaryResult = new Dictionary<string, MyClass>();
        result = new MyClass(objectId);
        dictionaryResult.Add(objectId, result);
        ActiveUsers.Add(myId, dictionaryResult);
    }
    else if (!dictionaryResult.TryGetValue(objectId, out result)) //otherwise check if the user already has this item
    {
        result = new MyClass(objectId);
        dictionaryResult.Add(objectId, result);
        ActiveUsers.Add(myId, dictionaryResult);
    }
    //else everything is already set-up
    return result;
}
公共静态MyClass GetInformation(字符串myId、字符串objectId)
{
//删除验证
Dictionary dictionaryResult=null;
MyClass结果=null;
if(!ActiveUsers.TryGetValue(myId,out dictionaryResult))//检查用户是否已添加到字典中
{
dictionaryResult=新字典();
结果=新的MyClass(objectId);
dictionaryResult.Add(objectId,result);
Add(myId,dictionaryResult);
}
else if(!dictionaryResult.TryGetValue(objectId,out result))//否则检查用户是否已经拥有此项
{
结果=新的MyClass(objectId);
dictionaryResult.Add(objectId,result);
Add(myId,dictionaryResult);
}
//否则一切都已经准备好了
返回结果;
}
编辑:显示如何删除内部项的代码

public static void RemoveUserAndSessions(string userId, string objectId)
{ 
    ActiveUsers.Remove(userId);
    foreach (Dictionary<string, MyClass> dic in ActiveUsers.Values)
        dic.Remove(objectId);
}
publicstaticvoidremoveUserAndSessions(stringuserid,stringobjectid)
{ 
ActiveUsers.Remove(userId);
foreach(ActiveUsers.Values中的字典dic)
dic.移除(objectId);
}
这是我使用的第一个ASP.NET应用程序,而且我以前没有做过任何涉及字典的多线程处理,如何使这个线程安全

编辑:试图让事情变得更清楚

我不想透露细节,但我想他们需要了解背后的原因。这是一个聊天应用程序。每个用户都存储在ActiveUsers中,以便跟踪活动用户。每个用户都有一个与之连接的客户端字典,MyClass对象包含客户端通信所需的一组属性。一旦用户断开连接,必须立即删除所有活动会话,因此使用delete方法。我想这可以通过创建另一个类来实现,该类在字典中保存活动会话,并将该类保存在原始字典中。

正如所建议的,我将看一看ConcurrentDictionary,我强烈建议按如下方式构建数据:

private static Dictionary<string, Dictionary<string, MyClass>> ActiveUsers = 
    new Dictionary<string, Dictionary<string, MyClass>>();
private static ConcurrentDictionary<string, ActiveUser> ActiveUsers { get; set; }

private class ActiveUser {
   public int ConnectionId { get; set; }
   public Dictionary<string, MyClass> MyClasses { get; set; } = new Dictionary<string, MyClass>();
}   
// . . . 
Dictionary<string, ActiveUser> ActiveUsers = new Dictionary<string, ActiveUser>();

编辑:为了清晰起见,重命名了一些内容。

从性能角度来看,我在您的设计中看到的主要问题是需要在
RemoveUserAndSessions
方法期间迭代所有字典。这是一个没有这个问题的示例设计

static class UserManager
{
    private static readonly Dictionary<string, User> ActiveUsers = new Dictionary<string, User>();
    public static User GetInformation(string userId)
    {
        lock (ActiveUsers)
        {
            User user;
            if (!ActiveUsers.TryGetValue(userId, out user))
                ActiveUsers.Add(userId, user = new User(userId));
            return user;
        }
    }
    public static void RemoveUserAndSessions(string userId)
    {
        lock (ActiveUsers)
        {
            User user;
            if (ActiveUsers.TryGetValue(userId, out user))
            {
                ActiveUsers.Remove(userId);
                user.EndAllSessions();
            }
        }
    }
    public static void StartSession(string firstUserId, string secondUserId)
    {
        lock (ActiveUsers)
        {
            var firstUser = GetInformation(firstUserId);
            var secondUser = GetInformation(secondUserId);
            firstUser.StartSession(secondUser);
            secondUser.StartSession(firstUser);
        }
    }
}
class User
{
    private Dictionary<string, User> sessions = new Dictionary<string, User>();
    public string Id { get; private set; }
    public User(string id) { Id = id; }
    public void StartSession(User other)
    {
        sessions.Add(other.Id, other);
    }
    public void EndSession(User other)
    {
        sessions.Remove(other.Id);
    }
    public void EndAllSessions()
    {
        foreach (var other in sessions.Values)
            other.EndSession(this);
        sessions.Clear();
    }
}
静态类用户管理器
{
私有静态只读字典ActiveUsers=new Dictionary();
公共静态用户GetInformation(字符串用户ID)
{
锁定(ActiveUsers)
{
用户;
if(!ActiveUsers.TryGetValue(userId,out user))
Add(userId,user=newuser(userId));
返回用户;
}
}
公共静态void RemoveUserAndSessions(字符串userId)
{
锁定(ActiveUsers)
{
用户;
if(ActiveUsers.TryGetValue(userId,out user))
{
ActiveUsers.Remove(userId);
EndAllSessions();
}
}
}
公共静态void StartSession(字符串firstUserId、字符串secondUserId)
{
锁定(ActiveUsers)
{
var firstUser=GetInformation(firstUserId);
var secondUser=GetInformation(secondUserId);
firstUser.StartSession(第二个用户);
secondUser.StartSession(第一个用户);
}
}
}
类用户
{
专用字典会话=新建字典();
公共字符串Id{get;private set;}
公共用户(字符串id){id=id;}
公共作废开始会话(用户其他)
{
sessions.Add(other.Id,other);
}
公共无效结束会话(用户其他)
{
sessions.Remove(其他.Id);
}
public void EndAllSessions()
{
foreach(sessions.Values中的其他变量)
其他.会议结束(本);
sessions.Clear();
}
}

这只是为了得到这个想法,希望你能将它映射到你的具体案例。

制作了一个控制台应用程序来测试这个。。。虽然嵌套字典需要0.15秒才能遍历50000个基本项和10个内部项,但列表需要57.34秒才能遍历同一个集合…确切地说,为什么要使用字典?几乎可以肯定的是,您不需要使用嵌套字典,而应该只设计一个类或接口。使用字典,尤其是嵌套字典,将使代码更加复杂,调试/维护更加困难。@R.Salisbury,因为在集合中查找特定对象的O(1)?通常使用的方法使用嵌套字典只需不到15行。您建议使用什么其他实现来实现这一点?您是对的,但是您仍然不应该使用字典字典。使用ActiveUsers或ActiveUserLookups字典,如果您确实需要另一个字典,请将其作为您分配给父字典值的类的属性,而不是字典本身的值。它只是让代码更容易阅读/维护。你是如何使用这本词典的?另外,您在多线程环境中使用的是
静态
字典,而字典不是线程安全的。我做了类似的事情,但我没有在MyClass中使用字典,而是使用了ConcurrentDictionary。我忘了并行。ForEach,谢谢你提醒我!编辑:顺便说一句,ConcurrentDictionary没有Remove方法,而是TryRemove