Sözlüğe <> güvenle bir öğe eklemenin daha zarif bir yolu var mı?


141

Bir sözlüğe anahtar / nesne çiftleri eklemeliyim, ama elbette önce anahtarın zaten var olup olmadığını kontrol etmem gerekiyor, aksi takdirde bir " anahtar zaten sözlükte var " hatası alıyorum. Aşağıdaki kod bunu çözer, ancak tıknazdır.

Böyle bir dize yardımcı yöntemi yapmadan bunu yapmanın daha zarif bir yolu nedir?

using System;
using System.Collections.Generic;

namespace TestDictStringObject
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, object> currentViews = new Dictionary<string, object>();

            StringHelpers.SafeDictionaryAdd(currentViews, "Customers", "view1");
            StringHelpers.SafeDictionaryAdd(currentViews, "Customers", "view2");
            StringHelpers.SafeDictionaryAdd(currentViews, "Employees", "view1");
            StringHelpers.SafeDictionaryAdd(currentViews, "Reports", "view1");

            foreach (KeyValuePair<string, object> pair in currentViews)
            {
                Console.WriteLine("{0} {1}", pair.Key, pair.Value);
            }
            Console.ReadLine();
        }
    }

    public static class StringHelpers
    {
        public static void SafeDictionaryAdd(Dictionary<string, object> dict, string key, object view)
        {
            if (!dict.ContainsKey(key))
            {
                dict.Add(key, view);
            }
            else
            {
                dict[key] = view;
            }
        }
    }
}

Yanıtlar:


246

Orada zaten eğer üzerine yazacaktır, ama değil - Sadece dizinleyici kullanmak zorunda : İlk orada olmak

Dictionary<string, object> currentViews = new Dictionary<string, object>();
currentViews["Customers"] = "view1";
currentViews["Customers"] = "view2";
currentViews["Employees"] = "view1";
currentViews["Reports"] = "view1";

Temel Addolarak, anahtarın varlığı bir hatayı (atmasını istiyorsanız) ve dizinleyiciyi aksi halde gösteriyorsa kullanın. ( asReferans dönüşümler için döküm ve kullanma arasındaki farka benziyor .)

C # 3 kullanıyorsanız ve farklı bir anahtar kümeniz varsa, bunu daha da temiz hale getirebilirsiniz:

var currentViews = new Dictionary<string, object>()
{
    { "Customers", "view2" },
    { "Employees", "view1" },
    { "Reports", "view1" },
};

Toplama başlatıcıları her zaman Addikinci Customersgirdiyi kullanacak şekilde kullandığından, durumunuzda çalışmayacaktır .


6
Mükemmel, basit atamanın ekleme / üzerine yazma sorununu hallettiğini fark etmedim, güzel.
Edward Tanguay

49

Sorun ne...

dict[key] = view;

Eğer yoksa anahtarı otomatik olarak ekler.


3
Düşündüğüm bir şey, bir int depolarsanız, dict[key] += amountanahtar yoksa işe yaramayacağını belirtmek gerekir
Chris S

22

basitçe

dict[key] = view;

Dictionary.Item MSDN belgelerinden

Belirtilen anahtarla ilişkilendirilmiş değer. Belirtilen anahtar bulunamazsa, bir get işlemi bir KeyNotFoundException özel durumu oluşturur ve bir set işlemi belirtilen anahtarla yeni bir öğe oluşturur .

Benim vurgu


10

Her zamanki gibi John Skeet, doğru cevapla aydınlatma hızına giriyor, ancak ilginç bir şekilde SafeAdd'ınızı IDictionary üzerine bir Genişletme Yöntemi olarak yazmış olabilirsiniz.

public static void SafeAdd(this IDictionary<K, T>. dict, K key, T value)...

9

Dizinleyiciyi kullanmak, özel sorununuz için açık bir şekilde doğru cevap olsa da, mevcut bir türe ek işlevsellik ekleme sorununa daha genel bir yanıt, bir uzantı yöntemi tanımlamak olacaktır.

Açıkçası bu özellikle yararlı bir örnek değil, ancak bir dahaki sefere gerçek bir ihtiyaç bulduğunuzda akılda tutulması gereken bir şey:

public static class DictionaryExtensions
{
    public static void SafeAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, 
                                             TKey key, TValue value)
    {
        dict[key] = value;
    }
}

2
Bunun sadece C # 3.0 ve üstü için geçerli olduğunu söyleyebilirim.
Mehrdad Afshari
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.