Có cách nào thanh lịch hơn để thêm một mục vào Từ điển <> một cách an toàn không?


141

Tôi cần thêm các cặp khóa / đối tượng vào từ điển, nhưng tất nhiên trước tiên tôi cần kiểm tra xem khóa đã tồn tại chưa nếu không tôi nhận được lỗi " khóa đã tồn tại trong từ điển ". Các mã dưới đây giải quyết điều này nhưng là clunky.

Một cách thanh lịch hơn để làm điều này mà không làm một phương thức trợ giúp chuỗi như thế này là gì?

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

Câu trả lời:


246

Chỉ cần sử dụng các Indexer - nó sẽ ghi đè lên nếu nó đã ở đó, nhưng nó không được ở đó đầu tiên:

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

Về cơ bản sử dụng Addnếu sự tồn tại của khóa chỉ ra một lỗi (vì vậy bạn muốn nó ném) và bộ chỉ mục khác. (Nó hơi giống sự khác biệt giữa truyền và sử dụng ascho chuyển đổi tham chiếu.)

Nếu bạn đang sử dụng C # 3 và bạn có một bộ khóa riêng biệt , bạn có thể làm cho nó gọn gàng hơn:

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

Điều đó sẽ không hoạt động trong trường hợp của bạn, vì các công cụ khởi tạo bộ sưu tập luôn sử dụng Addsẽ đưa vào Customersmục thứ hai .


6
Tuyệt vời, đã không nhận ra sự phân công đơn giản quan tâm đến vấn đề thêm / ghi đè, tốt đẹp.
Edward Tanguay

49

Có chuyện gì với...

dict[key] = view;

Nó sẽ tự động thêm khóa nếu nó không tồn tại.


3
Một điều tôi nghĩ đáng chú ý là nếu bạn đang lưu trữ một int, dict[key] += amountsẽ không hoạt động nếu khóa không tồn tại
Chris S

22

đơn giản

dict[key] = view;

Từ tài liệu MSDN của Dictionary.Item

Giá trị liên quan đến khóa được chỉ định. Nếu không tìm thấy khóa được chỉ định, thao tác get sẽ ném KeyNotFoundException và thao tác đã đặt sẽ tạo một phần tử mới với khóa được chỉ định .

Tôi nhấn mạnh


10

Như thường lệ, John Skeet đến đó với tốc độ ánh sáng với câu trả lời đúng, nhưng thú vị là bạn cũng có thể đã viết SafeAdd của mình dưới dạng Phương thức mở rộng trên IDadata.

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

9

Mặc dù sử dụng bộ chỉ mục rõ ràng là câu trả lời đúng cho vấn đề cụ thể của bạn, nhưng một câu trả lời chung chung khác cho vấn đề thêm chức năng bổ sung vào loại hiện có sẽ là xác định phương thức mở rộng.

Rõ ràng đây không phải là một ví dụ đặc biệt hữu ích, nhưng cần lưu ý lần sau khi bạn tìm thấy một nhu cầu thực sự:

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

2
Tôi muốn đề cập đến điều này chỉ áp dụng cho C # 3.0 trở lên.
Mehrdad Afshari
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.