80

我最近才注意到Dictionary.TryGetValue(TKey key, out TValue value)并很好奇哪种方法是从字典中检索值的更好方法。

我传统上做过:

if (myDict.Contains(someKey))
     someVal = myDict[someKey];
     ...

除非我知道它必须在那里。

这样做更好吗:

if (myDict.TryGetValue(somekey, out someVal)
    ...

哪个是更好的做法?一个比另一个快吗?我想 Try 版本会更慢,因为它在自身内部“吞下”一个 try/catch 并将其用作逻辑,不是吗?

4

4 回答 4

85

TryGetValue 稍微快一些,因为 FindEntry 只会被调用一次。

快多少?这取决于手头的数据集。当您调用 Contains 方法时,Dictionary 会进行内部搜索以查找其索引。如果它返回 true,则需要另一个索引搜索来获取实际值。当您使用 TryGetValue 时,它​​只搜索一次索引,如果找到,它会将值分配给您的变量。

仅供参考:它实际上并没有发现错误。

它在呼唤:

public bool TryGetValue(TKey key, out TValue value)
{
    int index = this.FindEntry(key);
    if (index >= 0)
    {
        value = this.entries[index].value;
        return true;
    }
    value = default(TValue);
    return false;
}

ContainsKey 是这样的:

public bool ContainsKey(TKey key)
{
    return (this.FindEntry(key) >= 0);
}
于 2008-12-18T16:53:26.240 回答
29

好吧,事实上 TryGetValue 更快。快多少?这取决于手头的数据集。当您调用 Contains 方法时,Dictionary 会进行内部搜索以查找其索引。如果它返回 true,则需要另一个索引搜索来获取实际值。当您使用 TryGetValue 时,它​​只搜索一次索引,如果找到,它会将值分配给您的变量。

编辑:

好的,我理解你的困惑,所以让我详细说明:

情况1:

if (myDict.Contains(someKey))
     someVal = myDict[someKey];

在这种情况下,有 2 次 FindEntry 调用,一次检查密钥是否存在,一次检索它

案例二:

myDict.TryGetValue(somekey, out someVal)

在这种情况下,只有一次对 FindKey 的调用,因为结果索引保留在同一方法中以供实际检索。

于 2008-12-18T17:02:10.467 回答
0

我想 trygetvalue 正在做的事情更像:

if(myDict.ReallyOptimisedVersionofContains(someKey))
{ 
  someVal = myDict[someKey];
  return true;
}
return false;

所以希望不要在任何地方尝试/捕捉。

我认为这只是一种方便的方法。我通常使用它,因为它可以节省一两行代码。

于 2008-12-18T16:54:37.890 回答
0
    public bool TryGetValue(TKey key, out TValue value)
{
  int index = this.FindEntry(key);
  if (index >= 0)
  {
    value = this.entries[index].value;
    return true;
  }
  value = default(TValue);
  return false;
}

public bool ContainsKey(TKey key)
{
  return (this.FindEntry(key) >= 0);
}

如您所见, TryGetValue 与 ContainsKey + 一个数组查找相同。

如果您的逻辑只是检查字典中是否存在该键,并且没有其他与该键相关的内容(获取键的值),您应该使用 ContainsKey。

也尝试检查这个类似的问题:is-there-a-reason-why-one-should-use-containskey-over-trygetvalue

于 2021-04-05T16:16:19.883 回答