2012-02-28 17 views
8

Hãy nói rằng tôi có một phương pháp như sau:C# tối ưu việc sử dụng IDictionary cho tra cứu với khả năng không tìm thấy

internal MyClass GetValue(long key) 
{ 
    if (_myDictionary.ContainsKey(key)) 
    return _myDictionary[key]; 

    return null; // Not found 
} 

IDictionary<long,MyClass> _myDictionary=... 

Nhưng đoạn mã trên có hai tra cứu trong từ điển:

  1. Các thử nghiệm cho sự tồn tại của khóa
  2. các hồi thực tế của giá trị

có cách nào tối ưu hơn để ph rase như một chức năng, do đó, chỉ có một tra cứu được thực hiện, nhưng trường hợp "không tìm thấy" vẫn được xử lý thông qua một trở về null (tức là, không thông qua một ngoại lệ không tìm thấy)?

Ví dụ, nó sẽ được tốt đẹp nếu tra cứu cho phím trở lại một số loại iterator mà có thể được sử dụng để lấy các giá trị hoặc một iterator không hợp lệ nếu giá trị không được tìm thấy như được thực hiện trong C++. Có lẽ C# có một cách tốt hơn để làm điều này cho các tính năng ngôn ngữ của nó.

Trả lời

16

Phương pháp TryGetValue được thiết kế cho kịch bản chính xác này - để tránh hai hoạt động tra cứu.

Phương pháp này kết hợp chức năng của phương pháp ContainsKey và thuộc tính Mục.

Nếu không tìm thấy khóa, thì thông số giá trị sẽ nhận được giá trị mặc định thích hợp cho loại giá trị TValue.

[...] Sử dụng phương pháp TryGetValue nếu mã của bạn thường xuyên cố truy cập các phím không có trong từ điển. Sử dụng phương pháp này hiệu quả hơn là so với việc nắm bắt KeyNotFoundException được ném bởi thuộc tính Item .

internal MyClass GetValue(long key) 
{ 
    MyClass maybeValue; 

    // Normally, one would inspect the return value of this method 
    // but in this case, it's not necessary since a failed lookup 
    // will set the out argument to default(valType), which is null 
    // for a reference type - exactly what you want. 
    _myDictionary.TryGetValue(key, out maybeValue); 

    return maybeValue; 
} 
+0

Thực hiện tốt, và bạn nhận được dấu kiểm không chỉ cho tốc độ nhập nhanh của bạn :), nhưng quan trọng hơn đối với nhận xét ở trên mã ... –

+0

Ngoài ra, điều này có thể được trừu tượng hơn nữa bằng cách sử dụng một phương pháp mở rộng: tĩnh T GetValue (từ điển này dict, phím TKey) {T tempVal = mặc định (T); dict.TryGetValue (khóa, ra tempVal); return tempVal; } ' – SPFiredrake

+0

@SPFiredrake, bạn nên đăng bài này như là một câu trả lời, tôi sẽ cung cấp cho bạn một upvote cho ý tưởng tuyệt vời. –

1

Bạn nên sử dụng TryGetValue thay - nó sử dụng một tra cứu duy nhất.

internal MyClass GetValue(long key) { 
    MyClass res = null; 
    _myDictionary.TryGetValue(key, out res) 
    return res; 
} 

Cuộc gọi đủ ngắn để sử dụng "nội tuyến", mà không thêm chức năng trình bao bọc. TryGetValue trả về số bool cho biết việc tra cứu có thành công hay không.

2

gõ lên SPFiredrakes ý tưởng ...

public static class Extensions 
{ 
    public static TValue GetValueOrDefault<TKey, TValue>(
      this IDictionary<Tkey, TValue> iDictionary, Tkey key) 
    { 
     TValue result; 
     return iDictionary.TryGetValue(key, out result) ? result : default(TValue) 
    } 
} 

sử dụng như thế này

var d = new Dictionary<long, SomeType> 
    {{1, new SomeType()}, {42, new SomeType()}, ...} 

var value1 = d.GetValueOrDefault(1); 
var value42 = d.GetValueOrDefault(42); 
var valueX = d.GetValueOrDefault(10); 

Tất nhiên, bây giờ bạn nên kiểm tra xem nếu giá trị của bạn null, có thể là lý do tại sao Net nhóm đã bỏ qua tính năng này.

Các vấn đề liên quan