Apakah ada cara yang lebih elegan untuk menambahkan item ke Kamus <> dengan aman?

141

Saya perlu menambahkan pasangan kunci / objek ke kamus, tapi tentu saja saya perlu memeriksa dulu apakah kunci sudah ada atau saya mendapatkan kesalahan " kunci sudah ada dalam kamus ". Kode di bawah ini menyelesaikan ini tetapi kikuk.

Apa cara yang lebih elegan untuk melakukan ini tanpa membuat metode string helper seperti ini?

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;
            }
        }
    }
}
Edward Tanguay
sumber

Jawaban:

246

Hanya menggunakan pengindeks - itu akan menimpa jika sudah ada, tetapi tidak memiliki berada di sana pertama:

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

Pada dasarnya gunakan Addjika keberadaan kunci menunjukkan bug (jadi Anda ingin membuangnya) dan pengindeks sebaliknya. (Ini sedikit seperti perbedaan antara casting dan menggunakan asuntuk konversi referensi.)

Jika Anda menggunakan C # 3 dan Anda memiliki serangkaian tombol yang berbeda , Anda dapat membuatnya lebih rapi:

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

Itu tidak akan berfungsi dalam kasus Anda, karena penginisialisasi koleksi selalu menggunakan Addyang akan memasukkan Customersentri kedua .

Jon Skeet
sumber
6
Luar biasa, tidak menyadari tugas sederhana menangani masalah add / overwrite, bagus.
Edward Tanguay
49

Ada apa dengan...

dict[key] = view;

Ini akan secara otomatis menambahkan kunci jika tidak ada.

Mehrdad Afshari
sumber
3
Satu hal yang saya pikir patut dicatat adalah jika Anda menyimpan int, dict[key] += amounttidak akan berfungsi jika kuncinya tidak ada
Chris S
22

secara sederhana

dict[key] = view;

Dari dokumentasi MSDN dari Dictionary.Item

Nilai yang terkait dengan kunci yang ditentukan. Jika kunci yang ditentukan tidak ditemukan, operasi get melempar KeyNotFoundException, dan operasi yang ditetapkan membuat elemen baru dengan kunci yang ditentukan .

Penekanan saya

Steve Gilham
sumber
10

Seperti biasa John Skeet tiba di sana dengan kecepatan pencahayaan dengan jawaban yang tepat, tetapi yang menarik Anda juga bisa menulis SafeAdd Anda sebagai Metode Ekstensi pada IDictionary.

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

Meskipun menggunakan pengindeks jelas merupakan jawaban yang tepat untuk masalah spesifik Anda, jawaban lain yang lebih umum untuk masalah penambahan fungsionalitas tambahan ke tipe yang ada adalah dengan mendefinisikan metode ekstensi.

Jelas ini bukan contoh yang sangat berguna, tetapi sesuatu yang perlu diingat untuk waktu berikutnya Anda menemukan kebutuhan nyata:

public static class DictionaryExtensions
{
    public static void SafeAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, 
                                             TKey key, TValue value)
    {
        dict[key] = value;
    }
}
Daniel Earwicker
sumber
2
Saya akan menyebutkan ini hanya berlaku untuk C # 3.0 dan di atas.
Mehrdad Afshari