このディクショナリキーがC#に存在するかどうかをどのように検出できますか?


498

連絡先データを使用して、Exchange Webサービスマネージ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が、PhysicalAddressDictionary方法があるので、ContainsTryGetValue彼らは同じように動作します。

使用例:

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

更新2:これが動作するコードです(question askerによってコンパイルされます)。

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

...必要なキーごとに、必要に応じて内部条件を繰り返します。TryGetValueは、PhysicalAddressKey(自宅、職場など)ごとに1回だけ実行されます。


TryGetValueこのページはgoo.gl/7YN6 ... であるので、この方法が最善の策であるように見えますが、使用方法がわかりません。上記の私のコードでrowはは 'DataRow`オブジェクトなので、サンプルコードが正しいかわかりませんが...
Adam Tuttle

ここで何が悪いのですか?c.PhysicalAddresses.TryGetValue(c.PhysicalAddresses[PhysicalAddressKey.Home].Street, row["HomeStreet"]);
Adam Tuttle、

1
@Adam Tuttle:2番目のパラメーターは出力パラメーターです。機能するコードを推測して回答を更新しますが、ここではコンパイルできないため、間違いを許さなければなりません。
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.