Bagaimana saya bisa mendeteksi jika kunci kamus ini ada di C #?

498

Saya bekerja dengan API yang Dikelola Layanan Web Exchange, dengan data kontak. Saya memiliki kode berikut, yang fungsional , tetapi tidak 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...
}

Seperti yang saya katakan, kode ini berfungsi . Sekarang saya ingin membuatnya sedikit menyusut , jika mungkin.

Saya tidak dapat menemukan metode apa pun yang memungkinkan saya memeriksa keberadaan kunci dalam kamus sebelum mencoba mengaksesnya, dan jika saya mencoba membacanya (dengan .ToString()) dan tidak ada maka pengecualian dilemparkan:

500
Kunci yang diberikan tidak ada dalam kamus.

Bagaimana saya bisa memperbaiki kode ini untuk menyedot lebih sedikit (sementara masih berfungsi)?

Adam Tuttle
sumber

Jawaban:

889

Anda bisa menggunakan ContainsKey:

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

atau TryGetValue:

dict.TryGetValue(key, out value);

Pembaruan : menurut komentar, kelas aktual di sini bukan IDictionarytapi PhysicalAddressDictionary, jadi metodenya Containsdan TryGetValuetetapi mereka bekerja dengan cara yang sama.

Contoh penggunaan:

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

Pembaruan 2: ini kode kerjanya (dikompilasi oleh penanya pertanyaan)

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

... dengan kondisi dalam diulangi seperlunya untuk setiap kunci yang diperlukan. TryGetValue hanya dilakukan sekali per PhysicalAddressKey (Rumah, Kantor, dll).

Mark Byers
sumber
The TryGetValuePendekatan tampaknya seperti itu mungkin menjadi taruhan terbaik, karena saya menemukan halaman ini: goo.gl/7YN6 ... tapi aku tidak yakin bagaimana menggunakannya. Dalam kode saya di atas, rowadalah objek 'DataRow`, jadi saya tidak yakin kode contoh Anda benar, meskipun ...
Adam Tuttle
Apa yang saya lakukan salah, di sini? c.PhysicalAddresses.TryGetValue(c.PhysicalAddresses[PhysicalAddressKey.Home].Street, row["HomeStreet"]);
Adam Tuttle
1
@Adam Tuttle: Parameter kedua adalah parameter keluar. Saya akan mencoba menebak kode yang berfungsi dan memperbarui jawaban saya, tetapi Anda harus memaafkan kesalahan karena saya tidak dapat mengompilasinya di sini.
Mark Byers
Jawaban yang bagus. Untuk konsistensi pada SO, istilah "penanya pertanyaan" dapat diganti dengan "OP" (kependekan dari Poster Asli).
Lave Loos
One liner (wajib C# 7.0)row["HomeStreet"] = c.PhysicalAddresses.TryGetValue(PhysicalAddressKey.Home, out PhysicalAddressEntry entry) ? entry.Street.ToString() : null;
Ivan García Topete
12

Apa jenis c.PhysicalAddresses? Jika itu Dictionary<TKey,TValue>, maka Anda dapat menggunakan ContainsKeymetode ini.

John Saunders
sumber
Terima kasih, Adam, itu benar-benar (tidak) membantu. Apa hirarki kelasnya? Apa tipe dasarnya?
John Saunders
3

Saya menggunakan Kamus dan karena pengulangan dan kemungkinan kunci yang hilang, saya dengan cepat menambal satu metode kecil:

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

Menyebutnya:

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

Mendapat pekerjaan.

JohanE
sumber
1

Ini sedikit sesuatu yang saya masak hari ini. Tampaknya bekerja untuk saya. Pada dasarnya Anda mengganti metode Tambahkan di ruang nama dasar Anda untuk melakukan pemeriksaan dan kemudian memanggil metode Tambahkan dasar untuk benar-benar menambahkannya. Semoga ini berhasil untuk Anda

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());
        }
    }
}
xul8tr
sumber