代码之家  ›  专栏  ›  技术社区  ›  mafu

如何使这个Dictionary TryGetValue代码更具可读性?

  •  6
  • mafu  · 技术社区  · 15 年前

    我想测试一个id是否还未知,或者,如果它已知,关联的值是否已经更改。我目前正在使用类似的代码,但是对于那些不熟悉该模式的人来说,很难理解。你能想出一个方法让它更可读,同时保持简短的LOC?

    string id;
    string actual;
    string stored;
    
    if (!someDictionary.TryGetValue (id, out stored) || stored != actual) {
        // id not known yet or associated value changed.
    }
    
    10 回复  |  直到 15 年前
        1
  •  1
  •   Mark Brackett    15 年前

    它看起来很好…读起来和其他任何2条件if语句一样简单。关于我唯一可能改变的事情是翻转否定词以便提前退出:

    if (someDictionary.TryGetValue(id, out stored) && stored == actual) {
        return;
    }
    // store new value
    

    我一点也不觉得这里面有什么混乱,也从来没有想过这是一个特别麻烦的习语,我谦恭地建议那些被它弄糊涂的开发者习惯它。它是常见的,简洁的,并给出了尽可能多的LOC的问题,因为它应该。把它变成10行代码 方式 太重要了。

    ContainsEqualValue

        2
  •  5
  •   max    15 年前

    您可以编写具有良好名称的扩展方法:

    public static class Utility
    {
        public static bool ValueChangedOrUnknown(this Dictionary<string, string> dictionary, string id, string actual)
        {
            string stored = null;
            return (!dictionary.TryGetValue(id, out actual) || stored != actual);
        }
    }
    

    所以以后你可以用

    string id;
    string actual;
    
    if (someDictionary.ValueChangedOrUnknown(id, actual) {
        // id not known yet or associated value changed.
    }
    
        3
  •  4
  •   Stefan Steinegger    15 年前

    所以我很可能会把它分开,给它起个有意义的名字。这是更多的阅读,但你不需要说太多的评论:

    bool isKnown = someDictionary.TryGetValue (id, out stored);
    // can only change when it is known
    bool valueChanged = isKnown && stored != actual;
    
    // quite self-explanatory, isn't it?
    if (!isKnown || valueChanged) 
    {
    
    }
    
        4
  •  3
  •   epitka    15 年前

    将| |的每个部分包装到它自己的方法或属性中,这样就可以这样编写了

    if ( IdIsNew() || IdChanged())
    
        5
  •  2
  •   leppie    15 年前

    二元性。

    if (!(someDictionary.TryGetValue (id, out stored) && stored == actual)) ...
    

        6
  •  1
  •   Sam Holder Brian Adams    15 年前

    我更喜欢一种新方法:

    public bool ShouldSetValue(Dictionary someDictionary, object id,object actualValue)
    {
        string stored;
    
        if (someDictionary.TryGetValue (id, out stored)) 
        {
            if (stored != actualValue)
                return true;
        }
        else
        {
            return true;
        }
    }
    

    在现有的方法中,我只想:

    if (ShouldSetValue(someDictionary,id,actual))
    {
         someDictionary[id]=actual;
    }
    
        7
  •  0
  •   Andrew Anderson    15 年前

    一个扩展的方法很巧妙:

    public static class DictionaryExtensions
    {
        public static bool ShouldAddValue<TKey, TValue>(this Dictionary<TKey, TValue> someDictionary, TKey id, TValue actual)
        {
            TValue stored;
            return (!someDictionary.TryGetValue(id, out stored) || !stored.Equals(actual)); 
        }
    }
    

    someDictionary.ShouldAddValue("foo", "bar")
    
        8
  •  0
  •   Jay    15 年前

    如果您的意思是必须重复执行此操作,而且它又长又难看,请将逻辑抽象到另一个类并使用扩展方法。

    public static class DictionaryExtensions
    {
        public static DictionaryChecker<TKey,TValue> contains<TKey,TValue>(this IDictionary<TKey,TValue> dictionary, TValue value)
        {
            return new DictionaryChecker<TKey,TValue>(value, dictionary);
        }
    }
    
    public class DictionaryChecker<TKey,TValue>
    {
        TValue value;
        IDictionary<TKey,TValue> dictionary;
    
        internal DictionaryChecker(TValue value, IDictionary<TKey, TValue> dictionary)
        {
            this.value = value;
            this.dictionary = dictionary;
        }
    
        public bool For(TKey key)
        {
            TValue result;
            return dictionary.TryGetValue(key, out result) && result.Equals(value);
        }
    }
    

    现在将代码替换为:

    if(!someDictionary.contains(actual).For(id)){
        // id not known yet or associated value changed.
    }
    
        9
  •  0
  •   Jake Kalstad    15 年前
    public T GetValue(int id, object actual)
    {
      object stored;
     if (someDictionary.TryGetValue (id, out stored) || stored == actual) 
        return stored;
      return new object();
    }
    
        10
  •  0
  •   supercat    15 年前

    虽然我认识到“try”模式是必要的,但我不喜欢需要“out”参数的实现。如果函数与TryGetValue类似,似乎会更有用:

    • TryGetDictValue(dictionary,key)如果key不在dictionary中,则返回null
    • TryGetDictValue(dictionary,key,defaultValue)如果key不在dictionary中,则返回defaultValue

    在任何情况下,结果的返回类型都是字典数据的返回类型。