在没有 System.Collections.Generic.KeyNotFoundException 的情况下对字典键的操作

Operations over dictionary-key without System.Collections.Generic.KeyNotFoundException

我有一个简单的字典调用结果:

Dictionary<String,String> results=new();
results["a"]="a";
results["b"]="b";
results["c"]="c";

为了简化示例,我的字典只包含 3 个字母键 a、b、c。 但有时它不会包含此值之一甚至 none,(它总是会被初始化)。 假设这种情况:

Dictionary<String,String> results=new();
if(anyconditionA) results["a"]="a";
if(anyconditionB)results["b"]="b";
if(anyconditionC)results["c"]="c";

所以每次我想使用这本词典时,我都必须检查键值: 变种测试=结果[“一”]; -> 如果任何条件 A 不为真,则抛出 System.Collections.Generic.KeyNotFoundException。 所以为了解决这个问题,我这样做了:

if(results.ContainsKey("a"){
  someOperation(results["a"]);
}

所以如果我有很多值,代码如下所示:

if(results.ContainsKey("a"){someOperation(results["a"]);}
if(results.ContainsKey("b"){... stuff}
if(results.ContainsKey("c"){... stuff}
if(results.ContainsKey("..."){... stuff}
if(results.ContainsKey("d"){someOperation(results["d"]);}

¿是否有一种正确的方法可以在一个语句中执行此操作,我的意思是检查并执行操作(如果存在),或者我必须在每次存在该值时进行测试? (就像在列表中使用 null 运算符一样 结果[a]?.someOperation() ) 谢谢!

如果你发现自己经常这样做并且想简化调用代码,你可以编写一个扩展方法:

public static class DictionaryExt
{
    public static bool DoIfExists<TKey, TValue>(this Dictionary<TKey, TValue> self, TKey key, Action<TValue> action)
    {
        if (!self.TryGetValue(key, out var value))
            return false;

        action(value);
        return true;
    }
}

那么你可以这样写代码:

results.DoIfExists("a", someOperation);

results.DoIfExists("b", value => Console.WriteLine("Doing stuff with " + value));

results.DoIfExists("c", value =>
{
    Console.WriteLine("Doing stuff with " + value);
    Console.WriteLine("This uses multiple lines.");
});

我真的不确定这是否值得(我不喜欢过度使用扩展方法),但这是一个见仁见智的问题!

在我看来,上面的第三个例子混淆了代码,最好写成:

if (results.TryGetValue("c", out var value))
{
    Console.WriteLine("Doing stuff with " + value);
    Console.WriteLine("This uses multiple lines.");
}

但第一个示例 results.DoIfExists("a", someOperation); 可以说比:

要简单一些
if (results.TryGetValue("a", out var value))
    someOperation(value);

这是一个边际改进,我个人不会打扰。由你决定!

您从 Matthew Watson 那里得到了“如果键不在字典中,则可能不调用获取值的操作”,但在您的问题末尾,您问的是一个稍微不同的问题

¿Is there a propper way to do this in one statement i mean check and do the operation if exists or i have to test every time that value exists? (like do with null operator in a list something like results[a]?.someOperation() ) Thanks!

如果操作是字典中值的方法,那么当然,您可以使用?.来防止对不存在的值的空引用:

        var dictionary = new Dictionary<int, StringBuilder>();

        dictionary.GetValueOrDefault(1)?.AppendLine("hello");

GetValueOrDefault 已实施 as an extension method and is a .net core 2.2+ thing. There are nuget packages that make it available for older versions, or you can write it yourself as an extension possibly adapting it from the netcore source 并将其放入您的应用程序:

    public static TValue? GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key)
    {
        return dictionary.GetValueOrDefault(key, default!);
    }

    public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
    {
        if (dictionary == null)
        {
            throw new ArgumentNullException(nameof(dictionary));
        }

        TValue? value;
        return dictionary.TryGetValue(key, out value) ? value : defaultValue;
    }