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)?

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.


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.


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.


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());
        }
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.