【问题标题】:Best way to handle a KeyNotFoundException处理 KeyNotFoundException 的最佳方法
【发布时间】:2009-03-03 14:41:38
【问题描述】:

我正在使用字典来查找我正在处理的程序。我通过字典运行了一堆键,我希望一些键没有值。我在它出现的地方抓住了KeyNotFoundException,并吸收了它。所有其他异常将传播到顶部。这是处理这个问题的最好方法吗?或者我应该使用不同的查找?字典使用 int 作为键,自定义类作为值。

【问题讨论】:

    标签: c# exception keynotfoundexception


    【解决方案1】:

    改用Dictionary.TryGetValue

    Dictionary<int,string> dictionary = new Dictionary<int,string>();
    int key = 0;
    dictionary[key] = "Yes";
    
    string value;
    if (dictionary.TryGetValue(key, out value))
    {
        Console.WriteLine("Fetched value: {0}", value);
    }
    else
    {
        Console.WriteLine("No such key: {0}", key);
    }
    

    【讨论】:

    • 是否仍然建议使用此方法而不是 ContainsKey()?
    • @SvenB:是的,我会这么说。为什么要进行两次查找,一次是检查键是否存在,一次是获取值,而您可以同时进行这两项操作?
    • @JonSkeet 我不知道如果 containskey 为假,我的猜测是避免不必要的分配。
    • @SvenB:如果 ContainsKey 为真,则将一项不必要的分配与再次执行整个查找的成本进行比较......我会惊讶地发现任何更有效的实际示例。
    • @JonSkeet 现在 dot.net 的新版本已经发布,也许更新答案并将string value 作为 TryGetValue 的一部分:if (dictionary.TryGetValue(key, out string value))
    【解决方案2】:

    尝试使用: Dict.ContainsKey

    编辑:
    性能方面,我认为Dictionary.TryGetValue 比其他一些建议更好,但我不喜欢在不需要的时候使用 Out,所以我认为 ContainsKey 更具可读性,但如果您也需要该值,则需要更多代码行。

    【讨论】:

    • 为什么它被否决了?请解释一下,以便我改进答案。
    • 你能解释一下为什么你不喜欢使用out,除非你必须这样做?
    • @wilbishard 这只是一种习惯,在我看来,我认为更难错过的是,当你有一个 = 符号时,可以更清楚地修改方法参数。现在这只是我的观点,并不意味着每个人都有相同的感觉,在某些情况下,最好的选择 int.TryParse 就是一个例子..
    【解决方案3】:

    使用TryGetValue的一条线解决方案

    string value = dictionary.TryGetValue(key, out value) ? value : "No key!";
    

    请注意,value 变量必须是字典在这种情况下返回 string 的类型。这里不能使用 var 进行变量声明。

    如果您使用的是 C# 7,在这种情况下,您可以包含 var 并内联定义它:

    string value = dictionary.TryGetValue(key, out var tmp) ? tmp : "No key!";
    

    这也是一个不错的扩展方法,它可以完全按照您想要的方式实现 dict.GetOrDefault("Key") 或 dict.GetOrDefault("Key", "No value")

    public static TValue GetOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue = default(TValue))
    {
          if (dictionary != null && dictionary.ContainsKey(key))
          {
               return dictionary[key];
          }
          return defaultValue;
     }
    

    【讨论】:

    • 当您有很多要查找的内容时,效果会更好,更简洁。
    【解决方案4】:

    这是一个单行解决方案(请记住,这会进行两次查找。请参阅下面的 tryGetValue 版本,它应该在长时间运行的循环中使用。)

    string value = dictionary.ContainsKey(key) ? dictionary[key] : "default";
    

    但我发现自己每次访问字典时都必须这样做。我希望它返回 null,所以我可以写:

    string value = dictionary[key] ?? "default";//this doesn't work
    

    【讨论】:

    • 避免使用此解决方案,因为它需要对字典进行两次查找。一次查找dictionary.ContainsKey,另一次查找dictionary[key]。使用@JernejNovak 的答案以获得更好的性能。
    • 有时性能不是优先考虑的,可读性更重要。 Jon Skeet 的答案不是你想要分散在你的代码中的东西。我会说在大循环中避免这种情况。我会在我的回答中注明。不过真的不值得投反对票。
    • string value = dictionary.ContainsKey(key) ? dictionary[key] : "default";string value = dictionary.TryGetValue(key, out value) ? value : "No key!"; 更具可读性吗
    • 老兄...当我写这个答案时,下面没有答案(这是一年多以前)。这就是为什么我将我的答案与 Jon Skeets 的答案进行比较的原因。其次,输出值可能更难阅读。用户可能不知道您不能使用 var 来初始化该值,并且不清楚该值在设置之前是否会被初始化。这是一个很好的解决方案,我会继续使用它,但它很棘手(它通过在已经设置好之后再次设置自己的值来工作)......这可能就是为什么有人花了一年多的时间来添加一个更好的解决方案。
    【解决方案5】:

    您应该使用 Dictionary 的 'ContainsKey(string key)' 方法来检查键是否存在。 对正常的程序流使用异常不是一种好的做法。

    【讨论】:

    • 正是我问这个问题的原因,我觉得我做的不是好习惯。
    【解决方案6】:

    我知道这是一个旧线程,但如果它有帮助,之前的答案很好,但是可以解决复杂性和乱扔代码的问题(对我也有效)。

    我使用自定义扩展方法以更优雅的形式将上述答案的复杂性包装起来,这样它就不会在整个代码中乱扔垃圾,然后它可以很好地支持 null coalesce operator 。 . .同时也最大限度地提高性能(通过上述答案)。

    namespace System.Collections.Generic.CustomExtensions
    {
        public static class DictionaryCustomExtensions
        {
            public static TValue GetValueSafely<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
            {
                TValue value = default(TValue);
                dictionary.TryGetValue(key, out value);
                return value;
            }
        }
    }
    

    然后你可以简单地通过导入命名空间System.Collections.Generic.CustomExtensions

    来使用它
    string value = dictionary.GetValueSafely(key) ?? "default";
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-02
      • 1970-01-01
      • 1970-01-01
      • 2020-09-12
      • 2019-08-06
      • 2013-09-02
      • 2019-02-23
      相关资源
      最近更新 更多