Wie kann ich feststellen, ob dieser Wörterbuchschlüssel in C # vorhanden ist?

498

Ich arbeite mit der von Exchange Web Services verwalteten API mit Kontaktdaten. Ich habe den folgenden Code, der funktionsfähig , aber nicht ideal ist:

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

Wie gesagt, dieser Code funktioniert . Jetzt möchte ich es , wenn möglich, etwas weniger lutschen lassen .

Ich kann keine Methoden finden, mit denen ich überprüfen kann, ob der Schlüssel im Wörterbuch vorhanden ist, bevor ich versuche, darauf zuzugreifen. Wenn ich versuche, ihn (mit .ToString()) zu lesen und er nicht vorhanden ist, wird eine Ausnahme ausgelöst:

500
Der angegebene Schlüssel war im Wörterbuch nicht vorhanden.

Wie kann ich diesen Code umgestalten, um weniger zu saugen (während ich noch funktionsfähig bin)?

Adam Tuttle
quelle

Antworten:

889

Sie können verwenden ContainsKey:

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

oder TryGetValue:

dict.TryGetValue(key, out value);

Update : Laut einem Kommentar ist die eigentliche Klasse hier keine, IDictionarysondern eine PhysicalAddressDictionary, also sind die Methoden Containsund TryGetValuesie funktionieren auf die gleiche Weise.

Anwendungsbeispiel:

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

Update 2: Hier ist der Arbeitscode (zusammengestellt vom Fragesteller)

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

... wobei die innere Bedingung nach Bedarf für jeden erforderlichen Schlüssel wiederholt wird. Der TryGetValue wird nur einmal pro PhysicalAddressKey (Home, Work usw.) ausgeführt.

Mark Byers
quelle
Der TryGetValueAnsatz scheint die beste Wahl zu sein , da ich diese Seite gefunden habe: goo.gl/7YN6 ... aber ich bin mir nicht sicher, wie ich ihn verwenden soll. In meinem obigen Code rowbefindet sich ein 'DataRow'-Objekt, daher bin ich mir nicht sicher, ob Ihr Beispielcode richtig ist ...
Adam Tuttle
Was mache ich hier falsch? c.PhysicalAddresses.TryGetValue(c.PhysicalAddresses[PhysicalAddressKey.Home].Street, row["HomeStreet"]);
Adam Tuttle
1
@ Adam Tuttle: Der zweite Parameter ist ein Out-Parameter. Ich werde versuchen, den Code zu erraten, der funktioniert, und meine Antwort aktualisieren, aber Sie müssen Fehler verzeihen, da ich ihn hier nicht kompilieren kann.
Mark Byers
Gute Antwort. Aus Gründen der SO-Konsistenz könnte der Begriff "Fragesteller" durch "OP" (kurz für Original Poster) ersetzt werden.
Lave Loos
Ein Liner (erforderlich C# 7.0)row["HomeStreet"] = c.PhysicalAddresses.TryGetValue(PhysicalAddressKey.Home, out PhysicalAddressEntry entry) ? entry.Street.ToString() : null;
Ivan García Topete
12

Was ist die Art von c.PhysicalAddresses? Wenn Dictionary<TKey,TValue>ja, können Sie die ContainsKeyMethode verwenden.

John Saunders
quelle
Danke, Adam, das ist wirklich (nicht) hilfreich. Wie ist die Klassenhierarchie? Was ist der Basistyp?
John Saunders
3

Ich benutze ein Wörterbuch und habe wegen der Wiederholbarkeit und möglicherweise fehlenden Schlüsseln schnell eine kleine Methode zusammengefügt:

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

Nennen wir es:

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

Erledigt die Arbeit.

JohanE
quelle
1

Hier ist etwas, das ich mir heute ausgedacht habe. Scheint für mich zu arbeiten. Grundsätzlich überschreiben Sie die Add-Methode in Ihrem Basis-Namespace, um eine Überprüfung durchzuführen, und rufen dann die Add-Methode der Basis auf, um sie tatsächlich hinzuzufügen. Hoffe das funktioniert bei dir

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