我目前有一个子项目的菜单存储在这个字典变量中:
private Dictionary<string, UserControl> _leftSubMenuItems
= new Dictionary<string, UserControl>();
所以我添加了视图,例如像这样的“客户”部分:
_leftSubMenuItems.Add("customers", container.Resolve<EditCustomer>());
_leftSubMenuItems.Add("customers", container.Resolve<CustomerReports>());
但由于我使用的是词典,我只能有一个名为“customers”的键。
我的自然倾向是现在创建一个带有“Section”和“View”属性的自定义结构,但是否有一个.NET集合更适合此任务,类似于一个“MultiKeyDictionary”?
感谢maciejkow,我扩展了你的建议,以获得我所需要的东西:
using System;
using System.Collections.Generic;
namespace TestMultiValueDictionary
{
class Program
{
static void Main(string[] args)
{
MultiValueDictionary<string, object> leftSubMenuItems = new MultiValueDictionary<string, object>();
leftSubMenuItems.Add("customers", "customers-view1");
leftSubMenuItems.Add("customers", "customers-view2");
leftSubMenuItems.Add("customers", "customers-view3");
leftSubMenuItems.Add("employees", "employees-view1");
leftSubMenuItems.Add("employees", "employees-view2");
foreach (var leftSubMenuItem in leftSubMenuItems.GetValues("customers"))
{
Console.WriteLine(leftSubMenuItem);
}
Console.WriteLine("---");
foreach (var leftSubMenuItem in leftSubMenuItems.GetAllValues())
{
Console.WriteLine(leftSubMenuItem);
}
Console.ReadLine();
}
}
public class MultiValueDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>
{
public void Add(TKey key, TValue value)
{
if (!ContainsKey(key))
Add(key, new List<TValue>());
this[key].Add(value);
}
public List<TValue> GetValues(TKey key)
{
return this[key];
}
public List<TValue> GetAllValues()
{
List<TValue> list = new List<TValue>();
foreach (TKey key in this.Keys)
{
List<TValue> values = this.GetValues(key);
list.AddRange(values);
}
return list;
}
}
}
感谢Blixt关于yield的提示,这里有GetAllValues的更改:
public IEnumerable<TValue> GetAllValues()
{
foreach (TKey key in this.Keys)
{
List<TValue> values = this.GetValuesForKey(key);
foreach (var value in values)
{
yield return value;
}
}
}
这是一个更简洁的方法来做同样的事情,谢谢基思:
public IEnumerable<TValue> GetAllValues()
{
foreach (var keyValPair in this)
foreach (var val in keyValPair.Value)
yield return val;
}
答案 0 :(得分:10)
如果一个键需要可变数量的值,为什么不创建Dictionary<string, List<UserControl>>
?此外,您可以继承此类并创建自己的Add,获得您现在使用的相同语法。这样,您可以在添加新控件之前避免手动添加空列表。
class MultiValueDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>
{
public void Add(TKey key, TValue value)
{
if(!ContainsKey(key))
Add(key, new List<TValue>());
this[key].Add(value);
}
}
答案 1 :(得分:5)
结帐NGenerics'HashList。它是一个字典,它维护每个键的值列表。 Wintellect's PowerCollections库还有一个方便的MultiDictionary类,可以在删除与给定键关联的最后一个值时自动清理。
答案 2 :(得分:4)
如何将容器值类型设为列表:
private Dictionary<string, List<UserControl>> _leftSubMenuItems =
new Dictionary<string, List<UserControl>>();
if (!_leftSubMenuItems.ContainsKey("customers"))
{
_leftSubMenuItems["customers"] = new List<UserControl>();
}
_leftSubMenuItems["customers"].Add(container.Resolve<EditCustomer>());
_leftSubMenuItems["customers"].Add(container.Resolve<CustomerReports>());
答案 3 :(得分:3)
只需进行一些调整......
public class MultiValueDictionary<TKey, TValue> :
Dictionary<TKey, List<TValue>>
{
public void Add(TKey key, TValue value)
{
List<TValue> valList;
//a single TryGetValue is quicker than Contains then []
if (this.TryGetValue(key, out valList))
valList.Add(value);
else
this.Add( key, new List<TValue> { value } );
}
//this can be simplified using yield
public IEnumerable<TValue> GetAllValues()
{
//dictionaries are already IEnumerable, you don't need the extra lookup
foreach (var keyValPair in this)
foreach(var val in keyValPair.Value);
yield return val;
}
}
答案 4 :(得分:2)
.NET framework 3.5包含一个特殊的LINQ Lookup类。
它类似于字典,只是它可以使用相同的键处理多个项目。当您使用给定键进行搜索时,您将收到一组与该键匹配的元素,而不是接收单个元素。
我读到它是一个哈希表,所以它很快就可以检索。
你使用这样的东西:
var example1 = (from element in ListWithDuplicates
select element)
.ToLookup(A => A.Name);
有一些警告:
Theres a great article here更详细地讨论了Lookup及其含义。
答案 5 :(得分:1)
不,没有更好的内置系列。我认为你的“自然倾向”非常适合解决这个问题,因为那些不是真正“相同的键”,但由不同部分组成的唯一键和Dictionary
完成了这项工作。您还可以嵌套字典(如果每个名称都有大量值,则有意义):
Dictionary<string, Dictionary<Type, object>> dict = ...;
var value = (T)dict[name][typeof(T)];
此方法将使用单个哈希表查找解析为该元素。如果你为每个元素维护一个项目列表,那么每次你需要一个元素进行查找时,你必须线性遍历列表,这首先会破坏使用Dictionary
的目的。
答案 6 :(得分:0)
我不知道“MultiKeyDictionary”。我建议使用结构并重写GetHashCode,Equals并实现IEquatable&lt; StructName&gt; (由Dictionary&lt; TKey,TValue&gt;使用)。
答案 7 :(得分:0)
您是否希望将每个密钥存储多个条目?类似this的内容?