6

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

string id;
string actual;
string stored;

if (!someDictionary.TryGetValue (id, out stored) || stored != actual) {
    // id not known yet or associated value changed.
}
4

10 回答 10

5

你可以写一个好名字的扩展方法:

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.
}
于 2010-06-10T13:38:25.447 回答
4

所以我很可能会把它分解并给它起有意义的名字。这需要阅读更多内容,但您不需要在评论中说太多:

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) 
{

}
于 2010-06-10T13:24:06.480 回答
3

包裹 || 的每一部分 到它自己的方法或属性中,而不是你可以这样写

if ( IdIsNew() || IdChanged())
于 2010-06-10T13:25:18.193 回答
2

二元性。

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

不确定它是否更具可读性......但很高兴知道。

于 2010-06-10T13:24:11.783 回答
1

我更喜欢一种新方法:

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;
}
于 2010-06-10T13:29:50.727 回答
1

对我来说它看起来不错……读起来和其他 2 个条件 if 语句一样简单。关于我唯一可能改变的事情是为了提前退出而翻转否定:

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

我完全没有看到它有任何混淆,从未认为它是一个特别麻烦的习语,并且谦虚地建议那些被它混淆的 C# 开发人员习惯它。它很常见,简洁,并且为问题提供了尽可能多的 LOC。把它变成 10 行代码就太重要了

如果我经常使用它,一个名为 like 的扩展方法ContainsEqualValue将是合适的 - 但我会在扩展方法中使用与您完全相同的代码。

于 2010-06-10T14:07:22.530 回答
0

扩展方法会很巧妙:

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")
于 2010-06-10T13:41:46.877 回答
0

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

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.
}
于 2010-06-10T13:44:05.140 回答
0
public T GetValue(int id, object actual)
{
  object stored;
 if (someDictionary.TryGetValue (id, out stored) || stored == actual) 
    return stored;
  return new object();
}
于 2010-06-10T14:37:38.347 回答
0

虽然我认识到“try”模式是必要的,但我不喜欢需要“out”参数的实现。具有类似于 TryGetValue 的功能似乎更有用:

  • TryGetDictValue(dictionary, key) 如果 key 不在字典中,则返回 null
  • TryGetDictValue(dictionary, key, defaultValue) 如果 key 不在字典中,则返回 defaultValue
  • TryGetDictValue(dictionary, key, valueReturningDelegate) 如果 key 不在字典中,则调用提供的委托并返回其结果

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

太糟糕了,没有办法潜入时间机器并让这些东西成为字典的方法。另一方面,可以将它们实现为以字典为第一个参数的静态函数。

于 2010-06-29T20:32:38.367 回答