【问题标题】:Dictionary Direct access vs TryGetValue字典直接访问与 TryGetValue
【发布时间】:2013-06-03 22:09:49
【问题描述】:

我有一个字典,它将字符串映射到这样的对象: Dictionary<string, object> myDic;

我事先知道对象的类型是基于字符串的,但我的问题是我应该使用 TryGetValue,还是使用 try、catch 语句直接查找。

例子:

//TryGetValueMethod
object myObject = null;
myDic.TryGetValue("test", out myObject);

MyCustomType t1 = (MyCustomType) myObject;

//Direct lookup method
try
{
     MyCustomType t2 = (MyCustomType) myDic["test"];
     //Do something here...
} catch {}

您认为哪种方法更受欢迎?第二个是更干净的编码,因为没有额外的强制转换,但我认为它比第一个效率低,因为它没有异常。

【问题讨论】:

  • 在字典中找不到该对象的预期行为是什么?
  • 如果你知道它的含义是什么,为什么还要使用Dictionary<string, object> 而不是Dictionary<string, MyCustomType>
  • 不,我可以有任何对象类型,但是有一个指定的字符串我知道值类型。例如,test 映射到 MyCustomType 对象,test1,映射到 MyCustomType2 对象。
  • 那个特别的catch { }。永远不要那样做。想都别想。
  • 是的,catch {} 只是为了举例。

标签: c# dictionary


【解决方案1】:

MSDN 说 “使用这个方法 [TryGetValue] 比捕获由 Item 属性抛出的 KeyNotFoundException 更有效。”

它还解释了TryGetValue “结合了ContainsKey 方法和Item 属性的功能”..

您还应该只捕获特定异常而不是所有异常。

更新:从 C# 7 开始,您现在可以编写:

if (myDic.TryGetValue("test", out MyCustomType value)) {
   // do something with value
}

【讨论】:

    【解决方案2】:

    我认为您不应该使用try/catch 来形成这样的逻辑路径。 Exceptions 应该是例外情况,即“出了问题”。

    我个人更喜欢ContainsKey

    if (myDic.ContainsKey("test")) {
       MyCustomType value = myDic["test"];
       // do something with the value
    }
    

    如果您认为找不到密钥意味着“出错”,那么我会省略测试,如果找不到密钥则抛出异常。

    编辑:这些天我尝试改用TryGetValue。稍微有点笨拙,但是一旦习惯了,就不会那么糟糕了。

    MyCustomType value;
    if (myDic.TryGetValue("test", out value)) {
       // do something with value
    }
    

    EDIT2:现在有了out var,我肯定会更多地使用TryGetValue。同样,您可以编写一个CantGetValue 方法(与相反的布尔结果相同),因为大多数时候您想在没有值时做一些额外的事情,而不是在有值时。

    if (dict.TryGetValue("test", out var value)) {
       // do something with value
    }
    
    // or
    
    if (cache.CantGetValue("test", out var cachedValue)) {
       // cache value
    }
    // make use of value
    

    【讨论】:

    • 是的,我认为最好使用 ContainsKey。当您想要进行强制转换时,它比 TryGetValue 编码更简洁,就像在这种情况下一样。
    • 为什么要查找两次才能查找一次。如果您有一个老式电话簿并想要某人的电话号码,您会查找一次,然后如果您发现它在其中,请关闭目录然后再​​次查找?
    【解决方案3】:

    如果您可以安全地预测密钥应该始终存在,则将其包装在 Try ... Catch 中。这样只有在出现问题时才会抛出异常。

    TryGetValue 是一个更好的选择 - Dictionary.ContainsKey(key) 一样好 - 最终它与 TryGetValue 在幕后做同样的事情。

    【讨论】:

    • “循环键直到找到(或没有)键”。我不认为这是正确的。字典是一个哈希表。 ContainsKeyTryGetValue 和索引都应该基本上是 O(1) 操作,而不是 O(n)。
    • 他们仍然做同样的事情,但是你是对的 - 这是一个哈希表。我会修改我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-07
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    • 1970-01-01
    相关资源
    最近更新 更多