深层嵌套字典是反模式吗?

我有一个结构可以使用三深嵌套字典很容易地表示,就像这样

private static Dictionary<string, Dictionary<string, Dictionary>> PrerenderedTemplates; 

结构可能会像这样使用

 PrerenderedTemplates[instanceID][templategroup][templatepart] 

现在,我意识到这段代码很难阅读,因为通过查看定义语句,你无法分辨出它的用途。 我可以在将其更改为Dictionary看到的唯一优势是可读性。 将每个嵌套转换为自己的类(例如, class PrerenderedTemplate{} class TemplateGroup{} class TemplatePart{} )将为很少(如果有)计算优势添加更多代码行。 据我所知。

  • 那么,我的方法是“好的”还是我应该加倍努力并创建单独的课程?
  • 是否可以覆盖嵌套Dictionary在文档/注释中的工作方式
  • 是否有处理这种嵌套的最佳实践?
  • 请记住,这是一个私人成员,对于使用该类的人来说,它不需要直截了当。

更新

所以,受Reza的启发,但无法使用Tuples,我决定创建自己的密钥生成器并实现他的模式:

 private Dictionary PrerenderedTemplates; private string GetPrerenderedTemplateKey(string InstanceId, string FeatureId, string OptionId) { return new StringBuilder(instanceId) .Append(FormatTools.LIST_ENTRY_DELIMITER) .Append(templategroup) .Append(FormatTools.LIST_ENTRY_DELIMITER) .Append(templatepart).ToString(); } 

其中FormatTools.LIST_ENTRY_DELIMITER是Unicode专用字符0xe04d

我提供另一种选择:

 Dictionary, string> pt; 

访问字典:

 pt[Tuple.Create("id","group","part")] 

更新

C#7中引入的价值元组最引人注目:

 Dictionary<(string id, string group, string part), string> pt; 

访问字典:

 pt[("id", "group", "part")] 

我会创建一个自定义词典。 像这样的东西

 public class TrippleKeyDict { private const string Separator = "<|>"; private Dictionary _dict = new Dictionary(); public string this[string key1, string key2, string key3] { get { return _dict[GetKey(key1, key2, key3)]; } set { _dict[GetKey(key1, key2, key3)] = value; } } public void Add(string key1, string key2, string key3, string value) { _dict.Add(GetKey(key1, key2, key3), value); } public bool TryGetValue(string key1, string key2, string key3, out string result) { return _dict.TryGetValue(GetKey(key1, key2, key3), out result); } private static string GetKey(string key1, string key2, string key3) { return String.Concat(key1, Separator, key2, Separator, key3); } } 

如果你认为,连接字符串是不够安全的,因为键可能包含分隔符,然后使用您自己的键类型或Touple作为键。 由于此实现细节隐藏在自定义词典中,因此您可以随时更改它。

你可以像这样使用字典

 var dict = new TrippleKeyDict(); // Using the Add method dict.Add(instanceID, templategroup, templatepart, "some value"); // Using the indexer dict[instanceID, templategroup, templatepart] = "xy"; string result = dict[instanceID, templategroup, templatepart]; // Using the TryGetValue method if (dict.TryGetValue(instanceID, templategroup, templatepart, out result)) { // Do something with result } 

我想提供一种替代方法,使用SortedDictionary和自定义比较器:

  public class PrerenderedTemplate { public string instanceID; public string templategroup; public string templatepart; public PrerenderedTemplate(string id, string tempGroup, string tempPart) { instanceID = id; templategroup = tempGroup; templatepart = tempPart; } // custom comparer instance used as argument // to SortedDictionary constructor public class Comparer : IComparer { public int Compare(PrerenderedTemplate x, PrerenderedTemplate y) { int compare = 0; if (compare == 0) compare = x.instanceID.CompareTo(y.instanceID); if (compare == 0) compare = x.templategroup.CompareTo(y.templategroup); if (compare == 0) compare = x.templatepart.CompareTo(y.templatepart); return compare; } } } 

使用方式如下:

  var dictionary = new SortedDictionary(new PrerenderedTemplate.Comparer()); dictionary.Add(new PrerenderedTemplate("1", "2", "3"), "123"); dictionary.Add(new PrerenderedTemplate("4", "5", "6"), "456"); dictionary.Add(new PrerenderedTemplate("7", "8", "9"), "789"); Assert.AreEqual(dictionary[new PrerenderedTemplate("7", "8", "9")], "789"); 

RezaArab的答案是有目的的,但我个人不喜欢Tuples基于他们的模糊属性和冗长的语法。

如果任何要求发生变化,带有比较器的自定义类可提供更高的清晰度和灵活性。