ฉันจะตรวจสอบได้อย่างไรว่าคีย์พจนานุกรมนี้มีอยู่ใน C # หรือไม่


498

ฉันกำลังทำงานกับ Exchange Web Services Managed 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
คีย์ที่ให้มาไม่ปรากฏในพจนานุกรม

ฉันจะสร้างรหัสนี้ใหม่ให้ดูดน้อยลงได้อย่างไร (ในขณะที่ยังใช้งานได้อยู่)

คำตอบ:


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

... พร้อมเงื่อนไขภายในซ้ำตามความจำเป็นสำหรับแต่ละคีย์ TryGetValue ทำเพียงครั้งเดียวต่อ PhysicalAddressKey (บ้านที่ทำงาน ฯลฯ )


TryGetValueวิธีดูเหมือนว่ามันอาจจะเป็นทางออกที่ดีที่สุดตั้งแต่ฉันพบหน้านี้: goo.gl/7YN6 ... แต่ผมไม่แน่ใจว่าวิธีการใช้งาน ในรหัสของฉันข้างต้นrowคือ 'DataRow` วัตถุดังนั้นผมไม่แน่ใจว่ารหัสตัวอย่างของคุณเป็นสิทธิ แต่ ...
อดัม Tuttle

ฉันทำอะไรผิดที่นี่ c.PhysicalAddresses.TryGetValue(c.PhysicalAddresses[PhysicalAddressKey.Home].Street, row["HomeStreet"]);
Adam Tuttle

1
@Adam Tuttle: พารามิเตอร์ตัวที่สองคือพารามิเตอร์ out ฉันจะพยายามเดารหัสที่ใช้งานได้และอัปเดตคำตอบของฉัน แต่คุณจะต้องให้อภัยข้อผิดพลาดเนื่องจากฉันไม่สามารถรวบรวมได้ที่นี่
Mark Byers

คำตอบที่ดี. เพื่อความสอดคล้องกับ SO คำว่า "ผู้ถามคำถาม" อาจถูกแทนที่ด้วย "OP" (ย่อมาจากโปสเตอร์ต้นฉบับ)
Lave Loos

สายการบินหนึ่งรายการ (ต้องใช้C# 7.0)row["HomeStreet"] = c.PhysicalAddresses.TryGetValue(PhysicalAddressKey.Home, out PhysicalAddressEntry entry) ? entry.Street.ToString() : null;
Ivan García Topete

12

ประเภทของc.PhysicalAddressesอะไร ถ้าเป็นDictionary<TKey,TValue>เช่นนั้นคุณสามารถใช้ContainsKeyวิธีการ


ขอบคุณอดัมมันมีประโยชน์จริงๆ ลำดับชั้นของคลาสคืออะไร? ประเภทฐานคืออะไร?
John Saunders


3

ฉันใช้พจนานุกรมและเนื่องจากความซ้ำซ้อนและกุญแจที่หายไปฉันจึงทำการปะรวมกันวิธีการเล็ก ๆ อย่างรวดเร็ว:

 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());
        }
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.