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)?

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


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.


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.


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());
        }
    }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.