【问题标题】:How can I detect if this dictionary key exists in C#?如何检测此字典键是否存在于 C# 中?
【发布时间】:2011-02-19 06:26:00
【问题描述】:

我正在使用 Exchange Web 服务托管 API 以及联系人数据。我有以下代码,功能性,但并不理想:

foreach (Contact c in contactList)
{
    string openItemUrl = "https://" + service.Url.Host + "/owa/" + c.WebClientReadFormQueryString;

    row = table.NewRow();
    row["FileAs"] = c.FileAs;
    row["GivenName"] = c.GivenName;
    row["Surname"] = c.Surname;
    row["CompanyName"] = c.CompanyName;
    row["Link"] = openItemUrl;

    //home address
    try { row["HomeStreet"] = c.PhysicalAddresses[PhysicalAddressKey.Home].Street.ToString(); }
    catch (Exception e) { }
    try { row["HomeCity"] = c.PhysicalAddresses[PhysicalAddressKey.Home].City.ToString(); }
    catch (Exception e) { }
    try { row["HomeState"] = c.PhysicalAddresses[PhysicalAddressKey.Home].State.ToString(); }
    catch (Exception e) { }
    try { row["HomeZip"] = c.PhysicalAddresses[PhysicalAddressKey.Home].PostalCode.ToString(); }
    catch (Exception e) { }
    try { row["HomeCountry"] = c.PhysicalAddresses[PhysicalAddressKey.Home].CountryOrRegion.ToString(); }
    catch (Exception e) { }

    //and so on for all kinds of other contact-related fields...
}

正如我所说,这段代码有效。如果可能的话,现在我想让它少一点。

我找不到任何方法可以让我在尝试访问它之前检查字典中的键是否存在,如果我尝试读取它(使用.ToString())并且它不存在那么抛出异常:

500
字典中没有给定的键。

我怎样才能重构这段代码以减少吸收(同时仍然有效)?

【问题讨论】:

    标签: c# exchangewebservices ews-managed-api


    【解决方案1】:

    你可以使用ContainsKey:

    if (dict.ContainsKey(key)) { ... }
    

    或TryGetValue:

    dict.TryGetValue(key, out value);
    

    更新:根据评论,这里的实际类不是IDictionary,而是PhysicalAddressDictionary,所以方法是Contains 和TryGetValue,但它们的工作方式相同.

    示例用法:

    PhysicalAddressEntry entry;
    PhysicalAddressKey key = c.PhysicalAddresses[PhysicalAddressKey.Home].Street;
    if (c.PhysicalAddresses.TryGetValue(key, out entry))
    {
        row["HomeStreet"] = entry;
    }
    

    更新 2:这是工作代码(由提问者编译)

    PhysicalAddressEntry entry;
    PhysicalAddressKey key = PhysicalAddressKey.Home;
    if (c.PhysicalAddresses.TryGetValue(key, out entry))
    {
        if (entry.Street != null)
        {
            row["HomeStreet"] = entry.Street.ToString();
        }
    }
    

    ...根据需要为每个所需的键重复内部条件。每个 PhysicalAddressKey(家庭、工作等)仅执行一次 TryGetValue。

    【讨论】:

    • TryGetValue 方法似乎是最好的选择,因为我找到了这个页面:goo.gl/7YN6... 但我不确定如何使用它。在我上面的代码中,row 是一个 'DataRow` 对象,所以我不确定你的示例代码是否正确......
    • 我做错了什么,在这里? c.PhysicalAddresses.TryGetValue(c.PhysicalAddresses[PhysicalAddressKey.Home].Street, row["HomeStreet"]);
    • @Adam Tuttle:第二个参数是一个输出参数。我将尝试猜测有效的代码并更新我的答案,但您必须原谅错误,因为我无法在这里编译它。
    • 好答案。为了在 SO 上保持一致,术语“提问者”可以替换为“OP”(原始海报的缩写)。
    • 一个班轮(需要C# 7.0)row["HomeStreet"] = c.PhysicalAddresses.TryGetValue(PhysicalAddressKey.Home, out PhysicalAddressEntry entry) ? entry.Street.ToString() : null;
    【解决方案2】:

    c.PhysicalAddresses 的类型是什么?如果是Dictionary<TKey,TValue>,则可以使用ContainsKey方法。

    【讨论】:

    • 谢谢,亚当,这真的(不)有帮助。什么是类层次结构?基本类型是什么?
    【解决方案3】:

    我使用字典,由于重复性和可能丢失的键,我快速拼凑了一个小方法:

     private static string GetKey(IReadOnlyDictionary<string, string> dictValues, string keyValue)
     {
         return dictValues.ContainsKey(keyValue) ? dictValues[keyValue] : "";
     }
    

    调用它:

    var entry = GetKey(dictList,"KeyValue1");
    

    完成工作。

    【讨论】:

      【解决方案4】:

      PhysicalAddressDictionary.TryGetValue

       public bool TryGetValue (
          PhysicalAddressKey key,
          out PhysicalAddressEntry physicalAddress
           )
      

      【讨论】:

        【解决方案5】:

        这是我今天煮的一些东西。似乎对我有用。基本上,您覆盖基本命名空间中的 Add 方法进行检查,然后调用基本命名空间的 Add 方法以实际添加它。希望这对你有用

        using System;
        using System.Collections.Generic;
        using System.Collections;
        
        namespace Main
        {
            internal partial class Dictionary<TKey, TValue> : System.Collections.Generic.Dictionary<TKey, TValue>
            {
                internal new virtual void Add(TKey key, TValue value)
                {   
                    if (!base.ContainsKey(key))
                    {
                        base.Add(key, value);
                    }
                }
            }
        
            internal partial class List<T> : System.Collections.Generic.List<T>
            {
                internal new virtual void Add(T item)
                {
                    if (!base.Contains(item))
                    {
                        base.Add(item);
                    }
                }
            }
        
            public class Program
            {
                public static void Main()
                {
                    Dictionary<int, string> dic = new Dictionary<int, string>();
                    dic.Add(1,"b");
                    dic.Add(1,"a");
                    dic.Add(2,"c");
                    dic.Add(1, "b");
                    dic.Add(1, "a");
                    dic.Add(2, "c");
        
                    string val = "";
                    dic.TryGetValue(1, out val);
        
                    Console.WriteLine(val);
                    Console.WriteLine(dic.Count.ToString());
        
        
                    List<string> lst = new List<string>();
                    lst.Add("b");
                    lst.Add("a");
                    lst.Add("c");
                    lst.Add("b");
                    lst.Add("a");
                    lst.Add("c");
        
                    Console.WriteLine(lst[2]);
                    Console.WriteLine(lst.Count.ToString());
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2010-12-08
          • 2012-03-27
          • 2016-03-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-06-23
          • 2021-11-02
          相关资源
          最近更新 更多