Làm cách nào để phát hiện nếu khóa từ điển này tồn tại trong C #?


498

Tôi đang làm việc với API được quản lý dịch vụ web trao đổi, với dữ liệu liên hệ. Tôi có đoạn mã sau, có chức năng , nhưng không lý tưởng:

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

Như tôi đã nói, mã này hoạt động . Bây giờ tôi muốn làm cho nó hút ít hơn một chút , nếu có thể.

Tôi không thể tìm thấy bất kỳ phương pháp nào cho phép tôi kiểm tra sự tồn tại của khóa trong từ điển trước khi thử truy cập nó và nếu tôi cố đọc nó (với .ToString()) và nó không tồn tại thì sẽ có một ngoại lệ:

500
Khóa đã cho không có trong từ điển.

Làm thế nào tôi có thể cấu trúc lại mã này để hút ít hơn (trong khi vẫn hoạt động)?

Câu trả lời:


889

Bạn có thể sử dụng ContainsKey:

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

hoặc TryGetValue:

dict.TryGetValue(key, out value);

Cập nhật : theo một nhận xét, lớp thực tế ở đây không phải là IDictionarymột PhysicalAddressDictionary, vì vậy các phương thức là ContainsTryGetValuenhưng chúng hoạt động theo cùng một cách.

Ví dụ sử dụng:

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

Cập nhật 2: đây là mã làm việc (được biên soạn bởi người hỏi)

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

... với điều kiện bên trong được lặp lại khi cần thiết cho mỗi khóa được yêu cầu. TryGetValue chỉ được thực hiện một lần cho mỗi PhysAddressKey (Gia đình, Công việc, v.v.).


Cách TryGetValuetiếp cận có vẻ như là đặt cược tốt nhất, vì tôi đã tìm thấy trang này: goo.gl/7YN6 ... nhưng tôi không chắc cách sử dụng nó. Trong mã của tôi ở trên, rowlà một đối tượng 'DataRow`, vì vậy tôi không chắc mã ví dụ của bạn là đúng, mặc dù ...
Adam Tript

Tôi làm gì sai ở đây? c.PhysicalAddresses.TryGetValue(c.PhysicalAddresses[PhysicalAddressKey.Home].Street, row["HomeStreet"]);
Adam T Ink

1
@Adam T Ink: Tham số thứ hai là tham số out. Tôi sẽ cố gắng đoán mã hoạt động và cập nhật câu trả lời của tôi nhưng bạn sẽ phải tha thứ cho những lỗi sai vì tôi không thể biên dịch nó ở đây.
Mark Byers

Câu trả lời tốt. Để thống nhất về SO, thuật ngữ "người hỏi" có thể được thay thế bằng "OP" (viết tắt của Poster gốc).
Lave Loos

Một lớp lót (yêu cầu C# 7.0)row["HomeStreet"] = c.PhysicalAddresses.TryGetValue(PhysicalAddressKey.Home, out PhysicalAddressEntry entry) ? entry.Street.ToString() : null;
Ivan García Topete

12

Các loại là c.PhysicalAddressesgì? Nếu đó là Dictionary<TKey,TValue>, sau đó bạn có thể sử dụng ContainsKeyphương pháp.


Cảm ơn, Adam, điều đó thực sự (không) hữu ích. Hệ thống phân cấp là gì? Loại cơ sở là gì?
John Saunders


3

Tôi sử dụng một Từ điển và vì tính lặp đi lặp lại và các khóa bị thiếu có thể, tôi nhanh chóng vá lại một phương pháp nhỏ:

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

Gọi nó là:

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

Được thực hiện công việc.


1

Đây là một chút gì đó tôi đã nấu lên ngày hôm nay. Dường như làm việc cho tôi. Về cơ bản, bạn ghi đè phương thức Thêm trong không gian tên cơ sở của mình để thực hiện kiểm tra và sau đó gọi phương thức Thêm của cơ sở để thực sự thêm phương thức. Hy vọng điều này làm việc cho bạn

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());
        }
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.