web-dev-qa-db-fra.com

Comment détecter si cette clé de dictionnaire existe en C #?

Je travaille avec l'API gérée des services Web Exchange, avec les données de contact. J'ai le code suivant, qui est fonctionnel, mais pas idéal:

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

Comme je l'ai dit, ce code fonctionne. Maintenant, je veux le faire sucer n peu moins, si possible.

Je ne trouve aucune méthode qui me permette de vérifier l'existence de la clé dans le dictionnaire avant d'essayer d'y accéder. Si j'essaie de la lire (avec .ToString()) et qu'elle n'existe pas, une exception est levée:

500
La clé donnée n'était pas présente dans le dictionnaire.

Comment puis-je refactoriser ce code pour qu'il aspire moins (tout en restant fonctionnel)?

431
Adam Tuttle

Vous pouvez utiliser ContainsKey :

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

ou TryGetValue :

dict.TryGetValue(key, out value);

Update : selon un commentaire, la classe réelle n'est pas un IDictionary mais un PhysicalAddressDictionary , si bien que les méthodes sont Contains et TryGetValue mais ils fonctionnent de la même manière.

Exemple d'utilisation:

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

Mise à jour 2: voici le code de travail (compilé par le demandeur)

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

... avec la condition interne répétée autant de fois que nécessaire pour chaque clé requise. TryGetValue n'est effectuée qu'une fois par PhysicalAddressKey (Home, Work, etc.).

795
Mark Byers

Quel est le type de c.PhysicalAddresses? S'il s'agit de Dictionary<TKey,TValue>, vous pouvez utiliser la méthode ContainsKey .

11
John Saunders

PhysicalAddressDictionary.TryGetValue

 public bool TryGetValue (
    PhysicalAddressKey key,
    out PhysicalAddressEntry physicalAddress
     )
5
David Neale

J'utilise un dictionnaire et à cause de la répétitivité et des éventuelles clés manquantes, j'ai rapidement corrigé une petite méthode:

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

L'appelant:

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

Fait le travail.

3
JohanE

Voici un petit quelque chose que j'ai concocté aujourd'hui. Semble travailler pour moi. Fondamentalement, vous substituez la méthode Add dans votre espace de noms de base pour effectuer une vérification, puis appelez la méthode Add de la base afin de l'ajouter réellement. J'espère que cela fonctionne pour toi

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