如何检测C#中是否存在此字典键?


497

我正在使用带有联系数据的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
给定的键在词典中不存在。

我如何重构此代码以减少错误(同时仍然起作用)?

Answers:


889

您可以使用ContainsKey

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

TryGetValue

dict.TryGetValue(key, out value);

更新:根据评论,这里的实际类不是,IDictionary而是a 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'对象,因此我不确定您的示例代码是否正确……
Adam Tuttle,2010年

我在做什么错,在这里?c.PhysicalAddresses.TryGetValue(c.PhysicalAddresses[PhysicalAddressKey.Home].Street, row["HomeStreet"]);
亚当·塔特尔

1
@Adam Tuttle:第二个参数是out参数。我将尝试猜测能起作用的代码并更新我的答案,但是您将不得不原谅错误,因为我无法在此处进行编译。
Mark Byers 2010年

好答案。为了保持SO的一致性,可以用“ OP”(原始海报的缩写)代替术语“问问者”。
Lave Loos 2015年

一支班轮(需要C# 7.0row["HomeStreet"] = c.PhysicalAddresses.TryGetValue(PhysicalAddressKey.Home, out PhysicalAddressEntry entry) ? entry.Street.ToString() : null;
伊万·加西亚·托皮特



3

我使用了Dictionary,并且由于重复性和可能丢失的键,我很快将一个小方法修补在一起:

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

调用它:

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

完成工作。


1

这是我今天煮的一些东西。似乎为我工作。基本上,您将覆盖基本名称空间中的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());
        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.