2010-02-24 24 views
5

Gần đây tôi đã làm việc trên thực hiện một đoạn nhỏ mà lưu trữ kết quả của tôi và cách tôi đã làm nó đã sử dụng một từ điển như sau:Hashset vs IQueryable

private Dictionary<ID, IQueryable<Results>> _simpleCache; 

Ý tưởng là để tìm kiếm tất cả các kết quả có id được chỉ định bởi 'ID' và nếu từ điển chứa id == khóa, chúng tôi chỉ cần tìm kiếm thông qua các giá trị có trong IQueryable thay vì thực hiện chuyến đi cơ sở dữ liệu.

tôi đã đi qua mảnh này của logic sáng nay và tôi đã suy nghĩ về việc thay thế IQueryable với HashSet như sau:

private Dictionary<ID, HashSet<Results>> _simpleCache; 

là làm cho sự thay đổi này nên?

Trả lời

13

Vâng, đúng vậy. Nói chung, IQueryable<T> ngụ ý rằng bạn đang sử dụng nhà cung cấp nguồn dữ liệu được truy vấn mỗi lần truy vấn được liệt kê (tất nhiên, đây không phải là luôn là trường hợp, vì bạn có thể gọi phương thức mở rộng AsQueryable trên IEnumerable<T>. IQueryable<T> triển khai thực hiện qua triển khai IEnumerable<T>).

Để kết thúc, lưu trữ IQueryable<Results> trong từ điển không thực sự ngăn bất kỳ lần truy cập nào đến nguồn dữ liệu khi bạn liệt kê thông tin này lần thứ hai. Nó sẽ gửi yêu cầu tới nhà cung cấp dữ liệu mỗi thời gian bạn liệt kê thông qua nó.

Bởi vì điều này, bạn thường muốn trở thành hiện thực các kết quả trên các mặt hàng, thường gọi phương pháp ToList hoặc ToArray phần mở rộng, và sau đó sử dụng IEnumerable<Results> hoặc Results[] như tham số TValue loại từ điển của bạn.

Lưu ý rằng bạn thể sử dụng một HashSet<T> để lưu trữ đối tượng của bạn, nhưng bạn phải chắc chắn rằng bạn thực hiện IEquatable<T> và ghi đè GetHashCode để comparer bình đẳng mặc định sẽ thực hiện một sự so sánh trên ID dụ tiếp xúc bởi các loại Results , hoặc là, hoặc bạn phải cung cấp một thực hiện IEqualityComparer<T> sẽ làm điều tương tự. Có nhiều khả năng bạn đang sử dụng mã do nhà thiết kế tạo ra, và nó sẽ không làm điều này cho bạn, và các đối tượng của bạn sẽ có sự bình đẳng được xác định bằng tham chiếu, chứ không phải bằng giá trị.