【发布时间】:2021-10-28 07:35:53
【问题描述】:
所以我有一个程序,它开始使用精确数量的步骤构建从给定起点到同一点的可能路径字典。
我首先为开始和结束步骤的每个独特组合添加一个字典行,然后我有一个方法,它基本上可以找到所有可以填充其间剩余步骤的独特组合。
看起来像这样:
private int CreatePathsWithAllSteps(int pathKey)
{
try
{
//Make sure we reiterate through the list of paths for all the configured steps to complete the paths.
for (int i = 0; i < MaxSteps - 2; i++)
{
//Create a fresh list of new paths with each complete iteration so we're not duplicating added paths
Dictionary<int, TravelPath> newPaths = new Dictionary<int, TravelPath>();
foreach (KeyValuePair<int, TravelPath> path in Paths)
{
//We need to find the list of Destination Pairs we can use with the existing path
Dictionary<string, DestinationPair> pairsToUse = FindDestinationPairsToUseNext(path, i+1);
bool isfirstiteration = true;
//***Issue*** 1 - Creating the copy of the KVP so I can reuse it to create all possible combinations of it with the next step in the path.
//I use the values of the KVP from the dictionary i'm iterating through. This seems to create them as reference paths back to the original dictionary.
KeyValuePair<int, TravelPath> pathCopy = new KeyValuePair<int, TravelPath>(path.Key, path.Value);
foreach (KeyValuePair<string, DestinationPair> TP in pairsToUse)
{
//Make sure we're using already existing paths first and then create new ones for all other options.
if (isfirstiteration)
{
//First time through use path already created at this point
if (path.Value.Path[i].Name != TP.Value.Name)
{
//Destination Pair is different to the previous pair so add it
path.Value.Path[i + 1] = TP.Value;
isfirstiteration = false;
}
}
else
{
//for this one, create a new copy of the path we're working on and then update with next step
if (pathCopy.Value.Path[i].Name != TP.Value.Name)
{
//***Issue*** 2 - When I use the value of the copied KVP to create a new KVP to add to the dictionary this also seems to create a reference back to the copy and by extension the original value from the original dictionary we're iterating through.
KeyValuePair<int, TravelPath> tempTP = new KeyValuePair<int, TravelPath>(pathKey, pathCopy.Value);
//***Issue*** 3 - I then edit the value of the KVP created in the previous line, and this changes the value in the original main Paths dictionary.
tempTP.Value.Path[i + 1] = TP.Value;
if (!PathValueComparer(tempTP, newPaths, Paths))
{
newPaths.Add(pathKey, pathCopy.Value);
pathKey++;
}
}
}
}
}
foreach(KeyValuePair<int, TravelPath> path in newPaths)
{
Paths.Add(path.Key, path.Value);
}
}
return pathKey;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return pathKey;
}
}
我添加了一些额外的带有 ***Issue*** 前缀的 cmets,这样您就可以看到我认为问题出在哪里以及我认为这里发生了什么。
现在距离我上次进行常规编码已经 3 或 4 年了,所以我有点生疏(请不要过多地评价我的代码,哈哈),但我确实记得以前在处理字典时遇到过类似的问题,并且我似乎记得解决方案是拥有一个同时实现 IDictionary 和 ICloneable 的自定义字典,因此您可以调用 .Clone() 来创建一个未引用的副本,然后可以对字典进行临时编辑并使用这些值而不会被引用回来到您的源字典。
我想我会尝试用 KVP 做一些类似的事情,但似乎没有一个 KVP 接口可以实际用作自定义实现的基础。
我觉得我可能只是创建一个可克隆的字典,然后在从克隆版本中获取我需要的 KVP 副本之前克隆它,但是对于这项工作,我真的不需要完整的字典可克隆,只是KVP,所以看起来有点浪费
所以我想问题是,有没有更好的方法来打破 KVP 和 Dictionary 的值之间的引用?
【问题讨论】:
-
这与
KeyValuePair无关(这是一个 struct,因此总是按值复制)以及与您的TravelPathclass,通过引用复制。你的问题到底是什么? -
@charlie 啊,好吧,在那种情况下,我想我的问题是我如何确保当我这样做时
tempTP.Value.Path[i + 1] = TP.Value;我确保字典值tempTP是从中复制的,它没有被编辑,它目前是……我想我的问题的解决方案是在我的 TravelPath 类中实现 ICloneable,然后我可以克隆 KVP 的值……听起来它可以解决问题。 -
确实,但我们对
TravelPath一无所知,因此无法提供建议 -
new KeyValuePair<int, TravelPath>(path.Key, path.Value);->new KeyValuePair<int, TravelPath>(path.Key, new TravelPath(...));? -
@caiusJard 哦,工作得很好,谢谢。
标签: c# .net dictionary key-value icloneable