虽然你可以通过实现自己的Equals
和GetHashCode
来使用类作为键,但如果你还不熟悉C#,我不建议这样做。
C#内部库会调用这些方法,并期望它们严格按照规范工作,优雅地处理所有边缘情况。如果你在其中放入一个错误,你可能需要经历一段不愉快的头痛时期。
在我看来,使用已经支持哈希和比较的经过尝试、验证和测试的现有类型来创建即时键无疑是效率更高、更简单的。
例如,从你的角度坐标开始:
int Bahn = 15
int Zeile = 30
你可以使用一个字符串(例如
"15,30"
):
String Key (int Bahn, int Zeile) { return $"{Bahn},{Zeile}"; }
var myDict = new Dictionary<string, string>();
myDict.Add (Key(Bahn,Zeile), myString);
或者如果你需要更高效的方式,可以返回一个包含两个元素的元组(例如<15,30>
):
Tuple<int,int> Key (int Bahn, int Zeile) { return Tuple.Create(Bahn,Zeile); }
var myDict = new Dictionary<Tuple<int, int>, string>();
myDict.Add (Key(Bahn,Zeile), myString);
或者,如果范围足够小以适合 int(例如 15+30*360
),则仅组合您的两个角度即可。如果需要更高效的方法:
int Key (int Bahn, int Zeile) { return Bahn+360*Zeile; }
var myDict = new Dictionary<int, string>();
myDict.Add (Key(Bahn,Zeile), myString);
这似乎比以下方式更简便:
class Key {
}
var myDict = new Dictionary<Key, string>();
myDict.Add (new Key(Bahn,Zeile), myString);
键的可变性
另外,请注意,只要用于索引条目,您的键必须是不可变的。
如果在使用键添加元素后更改Bahn
或Ziel
的值,则会严重破坏字典。
行为未定义,但您很可能会丢失随机条目,导致内存泄漏,并且如果内部库最终检测到不一致状态(例如由同一键索引的多个条目),则可能会崩溃并出现异常。
例如:
var myKey = new Key(15, 30);
for (String data in row_of_data_sampled_every_10_degrees)
{
myDict.Add (myKey, data); // myKey must remain constant until the entry is removed
myKey.Bahn += 10; // changing it now spells the death of your dictionary
}
关于哈希角度坐标的一点说明
现在问题是,为整数、字符串和元组提供的通用哈希函数可能不会为您特定的数据集产生最佳结果。
我建议从简单的解决方案开始,只有在遇到实际性能问题时才使用专门的代码。在这种情况下,您可能最好使用更适合空间索引的数据结构(通常是极坐标的四叉树,或者如果您想从扫描仪数据重建3D模型,则使用八叉树)。