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

发布于 2024-09-05 06:50:52 字数 299 浏览 3 评论 0原文

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

string id;
string actual;
string stored;

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

I'd like to test if an id was not yet known or, if it is known, if the associated value has changed. I'm currently using code similar to this, but it is hard to understand for those not familiar with the pattern. Can you think of a way to make it more readable while keeping it short in LOC?

string id;
string actual;
string stored;

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

尴尬癌患者 2024-09-12 06:50:52

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

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.
}

You can write an extension method with a good name:

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);
    }
}

so later you can use

string id;
string actual;

if (someDictionary.ValueChangedOrUnknown(id, actual) {
    // id not known yet or associated value changed.
}
暖心男生 2024-09-12 06:50:52

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

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

}

So I would most probably break it up and give it meaningful names. This is more to read, but you don't need much to say in comments:

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

}
仙女 2024-09-12 06:50:52

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

if ( IdIsNew() || IdChanged())

wrap each part of the || into its own method or property, than you can write it like this

if ( IdIsNew() || IdChanged())
π浅易 2024-09-12 06:50:52

二元性。

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

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

Duality.

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

Not sure if it is more readable though... but it's good to know.

丢了幸福的猪 2024-09-12 06:50:52

它对我来说看起来不错...读起来和任何其他 2 个条件 if 语句一样简单。我唯一可能改变的就是翻转否定以提前退出:

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

我根本没有看到任何混乱,从来没有认为它是一个特别麻烦的习惯用法,并谦虚地建议那些 C# 开发人员感到困惑就这样习惯了。它很常见、简洁,并且为问题提供了尽可能多的 LOC。将其变成 10 行代码使其变得太重要了。

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

It looks fine to me...reads as easy as any other 2 condition if statement. About the only thing I'd possibly change is to flip the negations for an early exit:

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

I don't see any confusion in it at all, have never thought of it as a particularly troublesome idiom, and humbly suggest that those C# devs confused by it get used to it. It's common, succint, and gives as many LOC to the problem as it deserves. Turning it into 10 lines of code makes it way too important.

If I used it often, an extension method named something like ContainsEqualValue would be appropriate - but I'd use the exact same code in the extension method as you have.

姜生凉生 2024-09-12 06:50:52

我更喜欢一种新方法:

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;
}

I'd prefer a new method:

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;
    }
}

then in the existing method I'd just:

if (ShouldSetValue(someDictionary,id,actual))
{
     someDictionary[id]=actual;
}
山色无中 2024-09-12 06:50:52

扩展方法会很灵活:

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

An extension method would be slick:

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)); 
    }
}

Usage:

someDictionary.ShouldAddValue("foo", "bar")
意犹 2024-09-12 06:50:52

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

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.
}

If you mean that you have to do this repeatedly, and it is long and ugly, abstract the logic to another class and use an extension method.

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);
    }
}

Now replace your code with:

if(!someDictionary.contains(actual).For(id)){
    // id not known yet or associated value changed.
}
萌无敌 2024-09-12 06:50:52
public T GetValue(int id, object actual)
{
  object stored;
 if (someDictionary.TryGetValue (id, out stored) || stored == actual) 
    return stored;
  return new object();
}
public T GetValue(int id, object actual)
{
  object stored;
 if (someDictionary.TryGetValue (id, out stored) || stored == actual) 
    return stored;
  return new object();
}
浮生未歇 2024-09-12 06:50:52

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

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

在每种情况下,结果的返回类型将是字典数据的返回类型。

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

While I recognize that the "try" pattern is necessary, I dislike implementations which require an "out" parameter. It would seem much more useful have functions similar to TryGetValue:

  • TryGetDictValue(dictionary, key) returns null if key is not in dictionary
  • TryGetDictValue(dictionary, key, defaultValue) returns defaultValue if key is not in dictionary
  • TryGetDictValue(dictionary, key, valueReturningDelegate) invokes the supplied delegate if key is not in dictionary and returns its result

In every case, the return type of the result would be that of the dictionary's data.

It's too bad there's no way to sneak into a time machine and make such things be methods of Dictionary. On the other hand, one could implement them as static functions taking a dictionary as the first parameter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文