Як я можу визначити, чи існує цей ключ словника в C #?


498

Я співпрацюю з API для керування веб-службами Exchange з контактними даними. У мене є такий код, який є функціональним , але не ідеальним:

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
Даного ключа в словнику не було.

Як я можу Refactor цього коду менше смоктати (поки він функціонує)?

Відповіді:


889

Ви можете використовувати 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();
    }
}

... із внутрішнім умовним повторенням у міру необхідності для кожного необхідного ключа. TryGetValue робиться лише один раз за PhysicalAddressKey (дім, робота тощо).


TryGetValueПідхід здається , що це може бути кращим вибором, так як я знайшов цю сторінку: goo.gl/7YN6 ... але я не знаю , як використовувати його. У моєму коді вище row- об’єкт "DataRow", тому я не впевнений, що ваш приклад код правильний, хоча ...
Адам Таттл

Що я тут роблю неправильно? c.PhysicalAddresses.TryGetValue(c.PhysicalAddresses[PhysicalAddressKey.Home].Street, row["HomeStreet"]);
Адам Таттл

1
@Adam Tuttle: Другий параметр - це вихідний параметр. Я спробую відгадати код, який працює, і оновити свою відповідь, але вам доведеться пробачити помилки, оскільки я тут не можу скласти.
Марк Байєрс

Хороша відповідь. Для узгодженості SO, термін "запитувач запитання" може бути замінений на "OP" (скорочення "Оригінальний плакат").
Lave Loos

Один лайнер (вимагає C# 7.0)row["HomeStreet"] = c.PhysicalAddresses.TryGetValue(PhysicalAddressKey.Home, out PhysicalAddressEntry entry) ? entry.Street.ToString() : null;
Іван Гарсія Топете

12

Який тип 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");

Здійснює виконану роботу.


1

Ось трохи чогось я приготував сьогодні. Здається, працює для мене. В основному ви переосмислюєте метод "Додати" у вашій базовій області імен, щоб зробити перевірку, а потім зателефонували до методу "Додати", щоб фактично додати його. Сподіваюся, це працює для вас

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());
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.