zoukankan      html  css  js  c++  java
  • c#扩展方法奇思妙用基础篇五:Dictionary<TKey, TValue> 扩展

    Dictionary<TKey, TValue> 类是常用的一个基础类,但用起来有时确不是很方便。本文逐一讨论,并使用扩展方法解决。

    向字典中添加键和值

    添加键和值使用 Add 方法,但很多时候,我们是不敢轻易添加的,因为 Dictionary<TKey, TValue> 不允许重复,尝试添加重复的键时 Add 方法引发 ArgumentException

    大多时候,我们都会写成以下的样子:

    var dict = new Dictionary<int, string>();
    // ...
    // 情形一:不存在才添加
    if (dict.ContainsKey(2) == false) dict.Add(2, "Banana");
    // 情形二:不存在添加,存在则替换
    if (dict.ContainsKey(3) == false) dict.Add(3, "Orange");
    else dict[3] = "Orange";

    其实,第二种情形可以写如下书写(请参见 http://msdn.microsoft.com/zh-cn/library/9tee9ht2.aspx):

    dict[3] = "Orange";

    不过好多朋友都会对这种方式表示疑虑,不太确定这样会不会出问题。

    不管是上面的哪种写法,用字典时最大的感觉就是担心,怕出异常,因此代码会写的很罗嗦。

    我每次用字典时都这样,时间长了,实在是厌烦了,索性扩展一下,用以下两个方法来应对上面两种情形:

    /// <summary>
    /// 尝试将键和值添加到字典中:如果不存在,才添加;存在,不添加也不抛导常
    /// </summary>
    public static Dictionary<TKey, TValue> TryAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue value)
    {
        if (dict.ContainsKey(key) == false) dict.Add(key, value);
        return dict;
    }
    /// <summary>
    /// 将键和值添加或替换到字典中:如果不存在,则添加;存在,则替换
    /// </summary>
    public static Dictionary<TKey, TValue> AddOrReplace<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue value)
    {
        dict[key] = value;
        return dict;
    }

    TryAdd 和 AddOrReplace 这两个方法具有较强自我描述能力,用起来很省心,而且也简单:

    dict.TryAdd(2, "Banana");
    dict.AddOrReplace(3, "Orange");

    或者像 Linq 或 jQuery 一样连起来写:

    dict.TryAdd(1, "A")
        .TryAdd(2, "B")
        .AddOrReplace(3, "C")
        .AddOrReplace(4, "D")
        .TryAdd(5, "E");

    再来看另外一个问题:

    获取值

    从字典中获取值通常使用如下方式:

    string v = "defaultValue";
    // 方式一
    if (dict.ContainsKey(3)) v = dict[3];
    // 方式二
    bool isSuccess = dict.TryGetValue(3, out v);

    使用索引的方式获取前一定先判断,否则不存在时会引发 KeyNotFoundException 异常。

    我尤其讨厌第二种方式,因为采用 out 要提前声明一个变量,代码至少要两行,不够简洁。

    看下 GetValue 扩展:

    /// <summary>
    /// 获取与指定的键相关联的值,如果没有则返回输入的默认值
    /// </summary>
    public static TValue GetValue<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, TValue defaultValue = default(TValue))
    {
        return dict.ContainsKey(key) ? dict[key] : defaultValue;
    }

    使用方便:

    var v1 = dict.GetValue(2);         //不存在则返回 null
    var v2 = dict.GetValue(2, "abc");  //不存在返回 ”abc“

    一行代码能搞定。

    批量添加

    List<T> 类有个 AddRange 方法,可以不用 foreach 循环直接向当前集合加入另外一个集合:

    List<string> roles = new List<string>();
    roles.AddRange(new[] { "role2", "role2" });
    roles.AddRange(user.GetRoles());

    相当方便,可怜 Dictionary<TKey, TValue> 类没有,幸好有扩展方法:

    /// <summary>
    /// 向字典中批量添加键值对
    /// </summary>
    /// <param name="replaceExisted">如果已存在,是否替换</param>
    public static Dictionary<TKey, TValue> AddRange<TKey, TValue>(this Dictionary<TKey, TValue> dict, IEnumerable<KeyValuePair<TKey, TValue>> values, bool replaceExisted)
    {
        foreach (var item in values)
        {
            if (dict.ContainsKey(item.Key) == false || replaceExisted)
                dict[item.Key] = item.Value;
        }
        return dict;
    }

    使用示例:

    var dict1 = new Dictionary<int, int>()
        .AddOrReplace(2, 2)
        .AddOrReplace(3, 3);
    var dict2 = new Dictionary<int, int>()
        .AddOrReplace(1, 1)
        .AddOrReplace(2, 1)
        .AddRange(dict1, false);

     

  • 相关阅读:
    生成html报告并整合自动发动邮件功能
    python--selenium多线程执行用例实例/执行多个用例
    python--selenium实用的自动生成测试HTML报告方法--HTMLTestRunner
    mysql完整版
    hibernate分页
    解决hibernate向mysql插入中文乱码问题
    c++语言的 代码组织
    命令总结
    c++ 命名空间
    dpkg 、apt
  • 原文地址:https://www.cnblogs.com/moss_tan_jun/p/1950554.html
Copyright © 2011-2022 走看看