我有一个可以使用三深嵌套字典很容易表示的结构,如此
private static Dictionary<string, Dictionary<string, Dictionary<string,string>>> PrerenderedTemplates;
结构可能会像这样使用
PrerenderedTemplates[instanceID][templategroup][templatepart]
现在,我意识到这段代码很难阅读,因为从查看定义语句来看,你无法分辨出它的用途。我将其更改为Dictionary<string, PrerenderedTemplate>
时唯一可以看到的优点是可读性。将每个嵌套转换为自己的类(例如class PrerenderedTemplate{} class TemplateGroup{} class TemplatePart{}
)将为很少(如果有的话)计算优势添加更多代码行。据我所见。
Dictionary
的工作原理
更新
所以,在Reza的启发下,但是无法使用Tuples,我决定创建自己的密钥生成器并实现他的模式:
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 :(得分:16)
我提供另一种选择:
Dictionary<Tuple<string, string, string>, string> pt;
访问字典:
pt[Tuple.Create("id","group","part")]
C#7 中引入的<强>更新强>:
Value Tuples 最引人注目:
Dictionary<(string id, string group, string part), string> pt;
访问字典:
pt[("id", "group", "part")]
答案 1 :(得分: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
}
答案 2 :(得分: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");
RezaArab 的回答是合适的,但我个人不喜欢Tuples基于他们的模糊属性和冗长的语法。
如果任何要求发生变化,带有比较器的自定义类可提供更高的清晰度和灵活性。