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

发布于 2024-09-01 19:54:07 字数 1375 浏览 13 评论 0原文

我正在使用 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
字典中不存在给定的键。

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

I am working with the Exchange Web Services Managed API, with contact data. I have the following code, which is functional, but not ideal:

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...
}

As I said, this code works. Now I want to make it suck a little less, if possible.

I can't find any methods that allow me to check for the existence of the key in the dictionary before attempting to access it, and if I try to read it (with .ToString()) and it doesn't exist then an exception is thrown:

500
The given key was not present in the dictionary.

How can I refactor this code to suck less (while still being functional)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

梦断已成空 2024-09-08 19:54:07

您可以使用 ContainsKey

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

TryGetValue

dict.TryGetValue(key, out value);

更新 :根据评论,这里的实际类不是 IDictionary 而是 PhysicalAddressDictionary,因此方法为包含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。

You can use ContainsKey:

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

or TryGetValue:

dict.TryGetValue(key, out value);

Update: according to a comment the actual class here is not an IDictionary but a PhysicalAddressDictionary, so the methods are Contains and TryGetValue but they work in the same way.

Example usage:

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

Update 2: here is the working code (compiled by question asker)

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

...with the inner conditional repeated as necessary for each key required. The TryGetValue is only done once per PhysicalAddressKey (Home, Work, etc).

梦里°也失望 2024-09-08 19:54:07

c.PhysicalAddresses 的类型是什么?如果是 Dictionary,那么您可以使用 ContainsKey 方法。

What is the type of c.PhysicalAddresses? If it's Dictionary<TKey,TValue>, then you can use the ContainsKey method.

单身狗的梦 2024-09-08 19:54:07

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

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

调用它:

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

完成工作。

I use a Dictionary and because of the repetetiveness and possible missing keys, I quickly patched together a small method:

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

Calling it:

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

Gets the job done.

世态炎凉 2024-09-08 19:54:07

改进的 JohanE 答案,具有泛型支持并作为扩展方法:

public static TValue GetKey<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dict, TKey key)
{
    return dict.ContainsKey(key) ? dict[key] : default;
}

调用它:

var entry = dict.GetKey("Key");

An improved JohanE answer, with generics support and as an extension method:

public static TValue GetKey<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dict, TKey key)
{
    return dict.ContainsKey(key) ? dict[key] : default;
}

Calling it:

var entry = dict.GetKey("Key");
在梵高的星空下 2024-09-08 19:54:07

PhysicalAddressDictionary.TryGetValue

 public bool TryGetValue (
    PhysicalAddressKey key,
    out PhysicalAddressEntry physicalAddress
     )

PhysicalAddressDictionary.TryGetValue

 public bool TryGetValue (
    PhysicalAddressKey key,
    out PhysicalAddressEntry physicalAddress
     )
流绪微梦 2024-09-08 19:54:07

这是我今天煮的一些东西。似乎对我有用。基本上,您重写基本命名空间中的 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());
        }
    }
}

Here is a little something I cooked up today. Seems to work for me. Basically you override the Add method in your base namespace to do a check and then call the base's Add method in order to actually add it. Hope this works for you

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());
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文