2012-02-16 117 views
16

我有一个可以使用三深嵌套的字典中很容易表示的结构,像这样深层嵌套字典是反模式吗?

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

凡结构可用于这样的事情

PrerenderedTemplates[instanceID][templategroup][templatepart] 

现在,我才知道这段代码很难阅读,因为从查看定义语句,你不能说出它的用途。我可以真正看到将其更改为Dictionary<string, PrerenderedTemplate>的唯一优点是可读性。将每个嵌套转换为它自己的类(例如class PrerenderedTemplate{} class TemplateGroup{} class TemplatePart{})会为很少(如果有的话)计算优势添加更多的代码行。据我所见。

  • 那么,我的方法是“好的”,还是应该多走一步并创建单独的课程?
  • 可以包括嵌套的Dictionary如何在文档/注释中工作
  • 是否有处理这种嵌套的最佳做法?
  • 请记住,这是一名私人会员,对于使用该课程的人而言,并不需要简单。

更新

因此,由礼启发,但无法使用元组,我决定创建自己的密钥生成器和执行他的模式是这样的:

private Dictionary<string, string> 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

+0

由于前两个嵌套基本上只是标识符,或许我可以摆脱一个简单的词典<字符串,字符串>。因此'PrerenderedTemplates [“instance1”] [“fruit”] [“banana”]'可以表示为'PrerenderedTemplates [“instance1_fruit_banana”]',就像一个名字空间。 – 2012-02-16 00:46:28

+0

您是否需要使用'PrerenderedTemplates'来列出您的模板组或模板部件? PrerenderedTemplates [instanceID] .Keys'或'PrerenderedTemplates [instanceID] [templateGroup]'的方式排序?如果是这样,那么这可能是最简单的方法来处理它。 – 2012-02-16 00:48:23

+0

@ M.Babcock,好吧,我正在循环包含指向如何呈现模板的元数据的对象集合。在渲染该模板之前,我想检查我的字典以确保它之前未被渲染。如果没有,我将它渲染并将结果添加到我的词典中。 (在其他地方处理模板更改管理) – 2012-02-16 00:55:25

回答

14

我提供了另一种选择:

Dictionary<Tuple<string, string, string>, string> pt; 

访问词典:

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

不错,我一定会给这一去,让你知道它是如何工作的! – 2012-02-16 00:58:36

+0

我不明白你的意思! – 2012-02-16 01:03:49

+2

对不起,Reza,我告诉你,我喜欢你的方法,我会尝试它。我应该尽量不要用那么多俚语。 – 2012-02-16 01:09:35

1

我想创建一个自定义词典。这样

public class TrippleKeyDict 
{ 
    private const string Separator = "<|>"; 
    private Dictionary<string, string> _dict = new Dictionary<string, string>(); 

    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<string,string,string>关键。由于此实现细节隐藏在自定义词典中,因此您可以随时更改它。

您可以使用字典这样

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 
} 
+1

我明白你的意思了。 'hello_world> hooray> stuff'和'hello> world_hooray> stuff'会发生冲突。两者都将使用键“hello_world_hooray_stuff”... – 2012-02-16 01:07:57

+0

我用'“|”'作为分隔符。您可以使用另一个您知道它从未在您的钥匙中使用的钥匙,如“<|>”。 – 2012-02-16 01:16:35

+0

我在构建这个框架时使用了一个非常模糊的unicode字符作为分隔符。敢说我会用它! :) – 2012-02-16 01:23:29

0

我想提供另一种方法,使用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<PrerenderedTemplate> 
     { 
      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<PrerenderedTemplate, string>(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<string>(dictionary[new PrerenderedTemplate("7", "8", "9")], "789"); 

Reza阿拉伯的答案是适合的目的,但我个人不喜欢元组的基础上它们的模棱两可的属性和冗长的语法。

与比较器的定制类提供了更清晰,也灵活,应任何要求的变化。