初始化Lookup

如何在c#中的对象初始化程序例程中为属性声明一个新的查找类?

例如

new Component() { ID = 1, Name = "MOBO", Category = new Lookup } 

类别位总是会出现编译错误。


我有一个名为Category的属性,其类型为Lookup ,我希望通过实例化此属性

 new Component() { ID = 1, Name = "MOBO", Category = new Lookup }; 

但我无法克服编译错误。

根据MSDN文档, Lookup类没有公共构造函数: http : //msdn.microsoft.com/en-us/library/bb460184.aspx

您可以通过在实现IEnumerable的对象上调用ToLookup来创建Lookup的实例。

你会想做类似的事情:

 new Component { ID = 1, Name = "MOBO", Category = new[] { … }.ToLookup(…) } 

更新以发表评论:

我不确定你从哪里获得类别信息,所以我会做些什么……

 new Component { ID = 1, Name = "MOBO", Category = new Dictionary { { 3, "Beverages" } { 5, "Produce" } }.ToLookup(o => o.Key, o => o.Value) } 

我的猜测是你的类别将来自其他来源,而不是像我在这里实例化的字典。

来自MSDN :

没有公共构造函数来创建Lookup的新实例。
此外, Lookup对象是不可变的,也就是说,在创建后,您无法在Lookup对象中添加或删除元素或键。

你不能只使用ToLookup; 你必须告诉它如何找到键和值:

 // from ChaosPandion's code using System.Linq; // make sure you have the using statement var component = new Component() { ID = 1, Name = "MOBO", Category = (Lookup) (new Dictionary() { {1, "one"} }) .ToLookup(p=>p.Key, p=>p.Value) } 

我不明白你为什么要在这里使用Lookup而不是字典。

这是我对此的尝试。 确保密钥是不可变的( Gist )。

 public class MultiValueDictionary : Collection, ILookup { public MultiValueDictionary(Func keyForItem) : base(new Collection(keyForItem)) { } new Collection Items => (Collection)base.Items; public IEnumerable this[TKey key] => Items[key]; public bool Contains(TKey key) => Items.Contains(key); IEnumerator> IEnumerable>.GetEnumerator() => Items.GetEnumerator(); class Collection : KeyedCollection, IEnumerable, IList { Func KeyForItem { get; } public Collection(Func keyForItem) => KeyForItem = keyForItem; protected override TKey GetKeyForItem(Grouping item) => item.Key; public void Add(TElement item) { var key = KeyForItem(item); if (Dictionary != null && Dictionary.TryGetValue(key, out var collection)) collection.Add(item); else Add(new Grouping(key) { item }); } public bool Remove(TElement item) { var key = KeyForItem(item); if (Dictionary != null && Dictionary.TryGetValue(key, out var collection) && collection.Remove(item)) { if (collection.Count == 0) Remove(key); return true; } return false; } IEnumerator IEnumerable.GetEnumerator() { foreach (var group in base.Items) foreach (var item in group) yield return item; } const string IndexError = "Indexing not supported."; public int IndexOf(TElement item) => throw new NotSupportedException(IndexError); public void Insert(int index, TElement item) => Add(item); public bool Contains(TElement item) => Items.Contains(item); public void CopyTo(TElement[] array, int arrayIndex) => throw new NotSupportedException(IndexError); new IEnumerable Items => this; public bool IsReadOnly => false; TElement IList.this[int index] { get => throw new NotSupportedException(IndexError); set => throw new NotSupportedException(IndexError); } } class Grouping : Collection, IGrouping { public Grouping(TKey key) => Key = key; public TKey Key { get; } } } 

查找使用与字典相同的概念,不同之处在于字典将映射到单个值 ,而查找映射是许多值

这也意味着:

 ILookup 

可以看作:

 IDictionary> 

当您想要将许多对象/值映射到同一个键时,您基本上想要使用ILookup 。 您可以从任何对象列表构建ILookup ,您可以通过某些属性对这些对象进行分组。 看到:

 public class Product { public string Name { get; set; } public string Category { get; set; } public decimal Price { get; set; } } var products = new List(); products.Add(new Product { Name = "TV", Price = 400, Category = "Electronics" }); products.Add(new Product { Name = "Computer", Price = 900, Category = "Electronics" }); products.Add(new Product { Name = "Keyboard", Price = 50, Category = "Electronics" }); products.Add(new Product { Name = "Orange", Price = 2, Category = "Fruits" }); products.Add(new Product { Name = "Grape", Price = 3, Category = "Fruits" }); // group by category ILookup lookup = products.ToLookup(prod => prod.Category); foreach (var item in lookup) { // this first loop would run two times // because there are two categories: Electronics and Fruits string category = item.Key; decimal totalPriceForCategory = item.Sum(i => i.Price); foreach (var product in item) { // for the electronics, this would loop three times // for the fruits, this would loop two times string name = product.Name; decimal price = product.Price; } } 

您还可以获得以下类别的所有产品:

 IEnumerable eletronics = lookup["Electronics"]; IEnumerable fruits = lookup["Fruits"];