【问题标题】:Hopefully simple question about modifying dictionaries in C#希望关于在 C# 中修改字典的简单问题
【发布时间】:2008-11-29 07:00:08
【问题描述】:

我在一个名为 current 的变量中有一个巨大的空白值字典,如下所示:

struct movieuser {blah blah blah}
Dictionary<movieuser, float> questions = new Dictionary<movieuser, float>();

所以我正在循环浏览这本字典,需要填写“答案”,如下所示:

for(var k = questions.Keys.GetEnumerator();k.MoveNext(); )
{
    questions[k.Current] = retrieveGuess(k.Current.userID, k.Current.movieID);
}

现在,这不起作用,因为我尝试修改正在循环的字典时收到 InvalidOperationException。但是,您可以看到代码应该可以正常工作 - 因为我没有添加或删除任何值,只是修改值。不过,我明白为什么它害怕我尝试这样做。

这样做的首选方法是什么?我想不出不使用迭代器来循环遍历字典的方法。

我真的不想创建整个数组的副本,因为它包含大量数据并且会像感恩节一样吃掉我的内存。

谢谢, 戴夫

【问题讨论】:

  • 经过深思熟虑,是不是因为字典将其存储在某种不断变化的二叉树或其他东西中,所以我无法编辑这些值?在这种情况下,如果您更改了值,它可能会更改列表的顺序,从而与迭代器发生冲突...
  • 在这种情况下,我想我必须创建一个临时键数组是有道理的......但我仍然不相信这是这种情况。

标签: c# .net dictionary


【解决方案1】:

马特的回答是,先拿到钥匙,分开是正确的方法。是的,会有一些冗余——但它会起作用。我会采用一个易于调试和维护的工作程序,而不是一个无法工作或任何一天都难以维护的高效程序。

不要忘记,如果您将MovieUser 设为引用类型,则数组的大小只会与您拥有的用户数量一样多——这非常小。一百万用户在 x64 上只会占用 4MB 或 8MB。你真的有多少用户?

因此,您的代码应该类似于:

IEnumerable<MovieUser> users = RetrieveUsers();

IDictionary<MovieUser, float> questions = new Dictionary<MovieUser, float>();
foreach (MovieUser user in users)
{
    questions[user] = RetrieveGuess(user);
}

如果您使用的是 .NET 3.5(因此可以使用 LINQ),那就更简单了:

IDictionary<MovieUser, float> questions = 
    RetrieveUsers.ToDictionary(user => user, user => RetrieveGuess(user));

请注意,如果RetrieveUsers() 可以从其源(例如文件)流式传输用户列表,那么无论如何它都会很有效,因为您在填充时不需要一次知道多个用户字典。

你的代码的其余部分的一些 cmets:

  • 代码约定很重要。将类型和方法的名称大写以适应其他 .NET 代码。
  • 您没有在调用GetEnumerator 产生的IEnumerator&lt;T&gt; 上调用Dispose。如果您只使用foreach,您的代码会更简单并且更安全。
  • MovieUser 几乎可以肯定是一个类。你真的有充分的理由让它成为一个结构吗?

【讨论】:

  • 我真的很感激你的洞察力——总的来说,我对 .NET 很陌生,来自 C++ 背景,所以这可以解释我的非传统想法。像这样的评论对我的学习很有帮助。
【解决方案2】:

你有什么理由不能同时用键和值填充字典吗?

foreach(var key in someListOfKeys)
{
    questions.Add(key, retrieveGuess(key.userID, key.movieID);
}

【讨论】:

  • 可能,但是你有问题字典的记忆加上一些键列表 - 这是多余的。不过感谢您的快速回复!
  • 那么...你从哪里得到钥匙现在
【解决方案3】:

将字典键存储在临时集合中,然后遍历临时集合并使用键值作为索引器参数。这应该可以让您绕过异常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 2020-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多