Начиная с .net3.5 + вместо использования Dictionary
вы можете использовать Lookup
из пространства имен Linq:
// lookup Order by payment status (1:m)
// would need something like Dictionary> orderIdByIsPayed
ILookup byPayment = orderList.ToLookup(o => o.IsPayed);
IEnumerable payedOrders = byPayment[false];
Из msdn :
Поиск похож на словарь. Разница заключается в том, что словарь сопоставляет ключи с одиночными значениями, тогда как Lookup сопоставляет ключи с коллекциями значений.
Вы можете создать экземпляр Lookup, вызвав ToLookup для объекта, который реализует IEnumerable.
blockquote>Вы также можете прочитать этот ответ на вопрос, связанный с . Для получения дополнительной информации см. msdn .
Полный пример:
using System; using System.Collections.Generic; using System.Linq; namespace LinqLookupSpike { class Program { static void Main(String[] args) { // init var orderList = new List
(); orderList.Add(new Order(1, 1, 2010, true));//(orderId, customerId, year, isPayed) orderList.Add(new Order(2, 2, 2010, true)); orderList.Add(new Order(3, 1, 2010, true)); orderList.Add(new Order(4, 2, 2011, true)); orderList.Add(new Order(5, 2, 2011, false)); orderList.Add(new Order(6, 1, 2011, true)); orderList.Add(new Order(7, 3, 2012, false)); // lookup Order by its id (1:1, so usual dictionary is ok) Dictionary orders = orderList.ToDictionary(o => o.OrderId, o => o); // lookup Order by customer (1:n) // would need something like Dictionary > orderIdByCustomer ILookup byCustomerId = orderList.ToLookup(o => o.CustomerId); foreach (var customerOrders in byCustomerId) { Console.WriteLine("Customer {0} ordered:", customerOrders.Key); foreach (var order in customerOrders) { Console.WriteLine(" Order {0} is payed: {1}", order.OrderId, order.IsPayed); } } // the same using old fashioned Dictionary Dictionary > orderIdByCustomer; orderIdByCustomer = byCustomerId.ToDictionary(g => g.Key, g => g.ToList()); foreach (var customerOrders in orderIdByCustomer) { Console.WriteLine("Customer {0} ordered:", customerOrders.Key); foreach (var order in customerOrders.Value) { Console.WriteLine(" Order {0} is payed: {1}", order.OrderId, order.IsPayed); } } // lookup Order by payment status (1:m) // would need something like Dictionary > orderIdByIsPayed ILookup byPayment = orderList.ToLookup(o => o.IsPayed); IEnumerable payedOrders = byPayment[false]; foreach (var payedOrder in payedOrders) { Console.WriteLine("Order {0} from Customer {1} is not payed.", payedOrder.OrderId, payedOrder.CustomerId); } } class Order { // key properties public Int32 OrderId { get; private set; } public Int32 CustomerId { get; private set; } public Int32 Year { get; private set; } public Boolean IsPayed { get; private set; } // additional properties // private List _items; public Order(Int32 orderId, Int32 customerId, Int32 year, Boolean isPayed) { OrderId = orderId; CustomerId = customerId; Year = year; IsPayed = isPayed; } } } } Замечание о неизменности
По умолчанию Lookups являются добрыми непреложного и доступ к
internal
s будет включать отражение. Если вам нужна изменчивость и вы не хотите писать свою собственную оболочку, вы можете использоватьMultiValueDictionary
(ранее известный какMultiDictionary
) из corefxlab (ранее частьMicrosoft.Experimental.Collections
, которая больше не обновляется).