1

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

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

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

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

所以每次我想用这本字典进行操作时,我都必须检查键值: var test= results["a"]; -> 如果 anycontitionA 不为真,则抛出 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 运算符一样 results[a]?.someOperation() )谢谢!

4

2 回答 2

2

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

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

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

于 2021-10-29T09:47:10.927 回答
2

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

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

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

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

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

GetValueOrDefault作为扩展方法实现,是 .net core 2.2+ 的东西。有一些 nuget 包使其可用于旧版本,或者您可以自己将其编写为扩展,可能从netcore 源对其进行调整并将其放入您的应用程序中:

    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;
    }
于 2021-10-29T10:00:41.103 回答