为什么Dictionary没有AddRange方法?

159

题目很基础,为什么我不能:

Dictionary<string, string> dic = new Dictionary<string, string>();
dic.AddRange(MethodThatReturnAnotherDic());

2
有很多东西没有AddRange,这一直让我感到困惑。比如Collection<>。总觉得很奇怪,List<>有它,但Collection<>或其他IList和ICollection对象却没有。 - Tim
50
我将模仿Eric Lippert的做法:“因为没有人设计、规定、实现、测试、记录并发布该功能。” - Gabe Moothart
5
@ Gabe Moothart - 这正是我所想的。 我喜欢向其他人使用那句话,但他们却不喜欢。 :) - Tim
2
@GabeMoothart,说“因为你不能”、“因为它不行”或者甚至是“因为。”不是更简单吗?——我猜这样说可能没有那么有趣之类的?--- 我对你的回答(我猜测是引用或转述)的跟进问题是:“为什么没有人设计、规定、实现、测试、文档化和发布该功能?”你很可能被迫回答“因为没有人这样做”,这与我之前提出的回答相当。我能想象的唯一另一个选项是不带讽刺意味的,也是OP实际上想知道的。 - Code Jockey
1
您可以间接地这样做: MethodThatReturnAnotherDic().ToList.ForEach(kvp => dic.Add(kvp.Key, kvp.Value));正如其他人所提到的,您可能需要小心处理重复项。 - Ama
显示剩余2条评论
13个回答

0

这是我其中一位同事编写的扩展函数,今天它救了我的命。HYG!

    /// <summary>
    /// Add key value pairs range to dictionary
    /// </summary>
    /// <param name="dictionary">current dictionary</param>
    /// <param name="range">new range to add</param>
    /// <typeparam name="TKey">dictionary key type</typeparam>
    /// <typeparam name="TValue">dictionary value type</typeparam>
    /// <returns>list of duplicate records that weren't added</returns>

public static IEnumerable<KeyValuePair<TKey, TValue>> AddRange<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, IDictionary<TKey, TValue> range)
       {
        var duplicateRecords = new List<KeyValuePair<TKey, TValue>>();
        
        foreach (var item in range)
        {
            if (dictionary.ContainsKey(item.Key))
                duplicateRecords.Add(item);
            else
                dictionary.Add(item);
        }
        return duplicateRecords;
    }

0

这里有一个使用c# 7的ValueTuples(元组字面量)的替代解决方案

public static class DictionaryExtensions
{
    public static Dictionary<TKey, TValue> AddRange<TKey, TValue>(this Dictionary<TKey, TValue> source,  IEnumerable<ValueTuple<TKey, TValue>> kvps)
    {
        foreach (var kvp in kvps)
            source.Add(kvp.Item1, kvp.Item2);

        return source;
    }

    public static void AddTo<TKey, TValue>(this IEnumerable<ValueTuple<TKey, TValue>> source, Dictionary<TKey, TValue> target)
    {
        target.AddRange(source);
    }
}

用法如下

segments
    .Zip(values, (s, v) => (s.AsSpan().StartsWith("{") ? s.Trim('{', '}') : null, v))
    .Where(zip => zip.Item1 != null)
    .AddTo(queryParams);

0

正如其他人所提到的,Dictionary<TKey,TVal>.AddRange没有被实现的原因是因为有多种方式可以处理重复情况。这也适用于Collection或者像IDictionary<TKey,TVal>ICollection<T>等接口。

只有List<T>实现了它,你会注意到IList<T>接口没有实现它,原因同样是:当向集合中添加一系列值时,期望的行为可以根据上下文而广泛变化。

你问题的背景表明你不担心重复,如果是这样,你可以使用一行代码的简单替代方案,使用Linq:

MethodThatReturnAnotherDic().ToList.ForEach(kvp => dic.Add(kvp.Key, kvp.Value));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接