【问题标题】:How to assign/add item(s) to a Dictionary using the key index?如何使用键索引将项目分配/添加到字典?
【发布时间】:2011-03-08 03:37:01
【问题描述】:

我们想使用键索引将项目分配/添加到字典,如下所示:

Dictionary<string, object> dict = new Dictionary<string, object>();
dict["key"] = dict["key"] ?? "object";

但它会导致:“字典中不存在给定的键。

有什么方法可以像我为会话分配值一样,使用 null 合并:

Session["Member"] = Session["Member"] ?? new Member();

谢谢

编辑: 我实际上试图从子类字典中覆盖索引器,但无济于事。 实现 IDictionary 接口似乎太多了,因为我们只需要下面代码的功能(即,如果找不到键,则返回 null)。 所以我想,也许我们可以使用如下扩展:

public static TValue [this Dictionary<TKey, TValue> thisDictionary, TKey key] {
    get { return thisDictionary.ContainsKey(key) ? thisDictionary[key] : null; }
    set { thisDictionary[key] = value; }
}

但它无法正常工作,甚至无法编译。

还有其他更简单的方法可以让我们重用这个索引器功能吗?非常感谢。

【问题讨论】:

    标签: dictionary c#-4.0 key key-value null-coalescing-operator


    【解决方案1】:

    如果你想内联:

    dict["key"] = dict.ContainsKey("key") ? (dict["key"] ?? "object") : "object"; 
    

    或者:

    dict["key"] = dict.ContainsKey("key") && dict["key"] == null ? dict["key"] : "object";
    

    根据 cmets 编辑:

    public static TValue GetSafe(this Dictionary<TKey, TValue> thisDictionary, TKey key) 
    { 
       if (!thisDictionary.ContainsKey(key))
           thisDictionary[key] = null;
    
       return thisDictionary[key];
    }
    

    这允许你这样做:

    thisDictionary["randomKey"] = thisDictionary.GetSafe("randomKey") ?? "someValue";
    

    【讨论】:

    • 好吧,如果我们这样做有点多余... =(
    • 取决于您是初始化对象还是引用变量。请参阅我的更新,了解纯三元/无空合并的替代方案。
    • 这和你问的不一样。您问我们是否可以使用 null 合并分配给字典是否已设置键。您的解决方案只是一种为您指定的键设置默认值的方法。
    • @Jronny,不包含key可以设置。
    • 应该是 dict["key"] = dict.ContainsKey("key") 吗? dict["key"] : "对象";
    【解决方案2】:

    如您所述,尝试获取丢失的键会引发异常。您必须先检查密钥是否存在:

    if( !Session.ContainsKey("Member") )
        Session["Member"] = new Member();
    

    编辑:

    并回答您的问题;您可以创建自己的索引器或实现 IDictionary 接口。这样就可以避免默认的抛出异常的行为

    【讨论】:

    • 很遗憾不能用扩展方法隐藏默认索引器。
    • 我不同意。如果您可以使用扩展方法隐藏方法,那么您肯定会遇到一些难以追踪的错误。例如,您不希望第三方库自动更改 object.Equals。或者更改您可能依赖的 IDictionary 行为。
    • 那也是反对继承的论据。
    • @Graphain:它可能......如果你不遵循 Liskov 的替换原则,你肯定也会遇到使用继承的问题。但是仅仅引用一个命名空间并在运行时以神秘的方式查看代码中断会更糟糕,因为您无法控制它。
    • 我猜,虽然这在某种程度上已经发生了——如果你声明一个与类同名的扩展方法,你的扩展方法将不会被调用,并且当多个程序集声明时扩展方法可能会发生冲突同名。
    猜你喜欢
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-20
    • 2012-09-26
    • 2020-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多