.Net 3.5不支持元组.太糟糕了,但不确定.net的未来版本是否会支持元组?
这是我直到今天才注意到的事情.显然,当执行基于相等的操作时Tuple<T>
,很多使用的元组类(Tuple<T1, T2>
等)的.NET实现会导致值类型的装箱惩罚.
以下是该类在框架中的实现方式(来自ILSpy的源代码):
public class Tuple<T1, T2> : IStructuralEquatable
{
public T1 Item1 { get; private set; }
public T2 Item2 { get; private set; }
public Tuple(T1 item1, T2 item2)
{
this.Item1 = item1;
this.Item2 = item2;
}
public override bool Equals(object obj)
{
return this.Equals(obj, EqualityComparer<object>.Default);
}
public override int GetHashCode()
{
return this.GetHashCode(EqualityComparer<object>.Default);
}
public bool Equals(object obj, IEqualityComparer comparer)
{
if (obj == null)
{
return false;
}
var tuple …
Run Code Online (Sandbox Code Playgroud) 我有一个结构可以使用三深嵌套字典很容易地表示,就像这样
private static Dictionary<string, Dictionary<string, Dictionary<string,string>>> PrerenderedTemplates;
Run Code Online (Sandbox Code Playgroud)
结构可能会像这样使用
PrerenderedTemplates[instanceID][templategroup][templatepart]
Run Code Online (Sandbox Code Playgroud)
现在,我意识到这段代码很难阅读,因为通过查看定义语句,你无法分辨出它的用途.我可以真正看到改变它的唯一优势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();
}
Run Code Online (Sandbox Code Playgroud)
FormatTools.LIST_ENTRY_DELIMITER
Unicode专用字符在哪里0xe04d
.
我一直在寻找一种方法来存储和检索超过C#的通用Dictionary类提供的单个键的值.
在网上搜索(以及SO本身)向我展示了几个选项:
基于元组的词典
.NET 4.0可以轻松支持通用的Tuple <,>类.这意味着您可以使用任意元组创建一个Dictionary,即
var myDict = new Dictionary<Tuple<Char, Int>, MyClass>();
嵌套字典
我了解到你也可以在Dictionaries中嵌套Dictionaries,这使得访问存储的结果类似于访问N维数组.例如:
Dictionary<int, Dictionary<int, Dictionary<Char, MyClass>>>
Run Code Online (Sandbox Code Playgroud)
然后可以通过以下方式获得: MyClass foo = MyData[8][3]['W'];
定界连锁键词典
但是,虽然两者都适用于复杂数据和自定义类,但我想知道它们是否总是必要的.至少对于原始数据,看起来将键与分隔符连接起来同样有效.
//keys are char + int
Dictionary<string, MyClass> myDict = New Dictionary<string, Myclass>();
String input = myChar + "|" + myInt
MyClass foo = myDict[input]
Run Code Online (Sandbox Code Playgroud)
是否存在使这些方法中的一种优于另一种方案的情景?他们会有类似的表演时间吗?或者重点应该放在哪种方法提供最干净,最容易维护的代码上?
思考?
假设我的字典需要由ItemId和RegionId的组合键入,两者都是int.并且说值侧的类型是"数据".我可以通过以下两种方式做到这一点:
方式1:多级字典,如下所示:
Dictionary<int, Dictionary<int, Data>> myData;
Run Code Online (Sandbox Code Playgroud)
所以查找可以像这样编码:
Data data1 = myData[itemId][regionId];
Run Code Online (Sandbox Code Playgroud)
不错,但缺点是我需要在第一级检查密钥存在,因此代码更安全
Data data1 = null;
if (myData.ContainsKey(itemId)) data1 = myData[itemId][regionId];
Run Code Online (Sandbox Code Playgroud)
方式2:使用多部分密钥.在这种方法中,我将创建一个表示部件的结构,并使用结构作为字典键:
private struct MultiPartKey
{
public int ItemId;
public int RegionId;
}
Dictionary<MultiPartKey, Data> myData;
Run Code Online (Sandbox Code Playgroud)
并且查找将是:
MultiPartKey mpk;
mpk.ItemId = itemId;
mpk.RegionId = regionId;
Data data1 = myData[mpk];
Run Code Online (Sandbox Code Playgroud)
这里可能的缺点是它只有在我的struct完全由简单值类型组成时才有效,因此两个实例的按位比较将是相等的.(对?)
你怎么看?
我有一个List<Thing> things
,其中一些Thing
需要通过看两个变量的组合经常检索小号T1 f1
和T2 f2
,这是值类型.我现在这样做的方式很简单things.Where(t => t.Field1 == f1 && t.Field2 == f2)
.但是,我经常进行极其多的查找,并且需要更有效的方法.
幸运的是,things
不需要删除或添加元素,所以我想在构造中解析列表并添加到Dictionary<T1, Lookup<T2, Thing>>
.但是,这感觉很麻烦,特别是添加了解析.如果我需要查找更多字段,它会变得非常毛茸茸.三个字段看起来像Dictionary<T1, Dictionary<T2, Lookup<T3, Thing>>>
.
我的下一个想法是做一个Lookup<Tuple<T1,T2,T3,...>,Thing>
.但在这种情况下,我不确定密钥是否真的有效,因为Tuple是一个引用类型.
即使我做了一个Lookup<ValueType<T1,T2,T3,...>,Thing> things
,查找语句将things[new ValueType<T1,T2,T3,...>(f1, f2, f3, ...)]
是非常难看的(我仍然不确定我是否可以信任这些键).
有没有更优雅的解决方案,这保持哈希表的性能优势,我可以简单地输入类似的东西IEnumerable<Thing> found = things[f1, f2, f3, ...];
?
使用System.Collections
如何使用两个主键创建集合?
我的意思是避免使用相同组合的新条目,但每个键可以与其他键一起使用(例如组合两个主键SQL
)
这段代码
Tuple<int,double>[, ,] myArray = new Tuple<int, double> () [xsize, ysize, zsize];
Run Code Online (Sandbox Code Playgroud)
返回此错误
无法将带有[]的索引应用于"Tuple"类型的表达式
我在哪里使用这里Tuple
定义的结构.
感谢您的帮助,非常感谢本网站的作者,这个网站对我的日常工作有很大的帮助.
c# ×7
.net ×4
dictionary ×4
tuples ×2
.net-3.5 ×1
boxing ×1
collections ×1
hashtable ×1
key ×1
oop ×1
performance ×1
primary-key ×1