이 사전 키가 C #에 있는지 어떻게 알 수 있습니까?


498

연락처 데이터를 사용하여 Exchange 웹 서비스 관리 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...
}

내가 말했듯 이이 코드 는 작동합니다 . 이제 가능하다면 조금 덜 빨리 게 만들고 싶습니다 .

액세스하기 전에 사전에 키가 있는지 확인할 수있는 메소드를 찾을 수 없으며 (with .ToString()) 키 를 읽으려고하면 존재하지 않으면 예외가 발생합니다.

500
주어진 키가 사전에 없습니다.

이 코드를 리팩터링하여 덜 빨리려면 (여전히 기능적 일 때) 어떻게해야합니까?

답변:


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 당 한 번만 수행됩니다 (집, 직장 등).


goo.gl/7YN6 ... TryGetValue이 페이지를 찾은 후이 방법 이 최선 의 방법 일 것 같습니다 . 위의 코드 row에서 'DataRow` 객체이므로 예제 코드가 올바른지 잘 모르겠습니다.
Adam 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.0row["HomeStreet"] = c.PhysicalAddresses.TryGetValue(PhysicalAddressKey.Home, out PhysicalAddressEntry entry) ? entry.Street.ToString() : null;
필수

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.