我的代码中有一些内存不足的问题,在我重构一个方法之后,更通用的东西,我可以用我的参数调用它。 更改之前的方法立即响应,即使它正在读取数千行,而重构的方法耗尽内存并且看起来很重。
private Dictionary<string, string> MapFile(string[] fileRows)
{
var dic = new Dictionary<string, string>();
foreach (var row in fileRows)
{
var key = row.Substring(3, 10) + row.Substring(45, 11);
dic[key] = row;
}
return dic;
}
糟糕的方法:
private Dictionary<string, string> MapFile(string[] fileRows, params KeyValuePair<int, int>[] keyIndexes)
{
var dic = new Dictionary<string, string>();
StringBuilder keyPair = new StringBuilder();
foreach (var row in fileRows)
{
foreach (var keyIndex in keyIndexes)
{
keyPair.Append(row.Substring(keyIndex.Key, keyIndex.Value));
}
dic[keyPair.ToString()] = row;
}
return dic;
}
称之为:
MapFile(file, new KeyValuePair<int,int>(3,10), new KeyValuePair<int,int>(45,11))
我理解代码需要做更多的工作,但仍然不理解读取这两种方法之间的巨大差异。一个是平滑的,在不到一秒的时间内响应,另一个占用系统的所有内存,然后崩溃。
Upate:
想知道,如果这个实现,使用Tuple作为存储一对int的类型,在方法(索引,长度)内使用Substring是更聪明和更好的做法吗?
private Dictionary<string, string> MapFile(string[] fileRows, params Tuple<int, int>[] keyIndexes)
{
var dic = new Dictionary<string, string>();
foreach (var row in fileRows)
{
string key = "";
foreach (var pair in keyIndexes)
{
key += row.Substring(pair.Item1, pair.Item2);
}
dic[key] = row;
}
return dic;
}
答案 0 :(得分:3)
基本上,问题是你要在每一行上向StringBuilder附加2个值,所以在每个循环中你都会让StringBuilder存储更大的值,直到你的内存不足为止
相反,您应该做的是,逻辑与先前版本不同,是:
foreach (var row in fileRows)
{
StringBuilder keyPair = new StringBuilder(); // Create a new instance each time
foreach (var keyIndex in keyIndexes)
{
keyPair.Append(row.Substring(keyIndex.Key, keyIndex.Value));
}
dic[keyPair.ToString()] = row;
}
如果你只想使用StringBuilder的一个实例,你可以这样做:
StringBuilder keyPair = new StringBuilder();
foreach (var row in fileRows)
{
foreach (var keyIndex in keyIndexes)
{
keyPair.Append(row.Substring(keyIndex.Key, keyIndex.Value));
}
dic[keyPair.ToString()] = row;
keyPair.Clear(); // ensure it is cleared for the next row
}
你可以做的另一件事就是这样,所以你不必处理StringBuilder:
foreach (var row in fileRows)
{
string key = string.Empty;
foreach (var keyIndex in keyIndexes)
{
key += row.Substring(keyIndex.Key, keyIndex.Value);
}
dic[key] = row;
}
答案 1 :(得分:2)
StringBuilder keyPair = new StringBuilder();
foreach (var row in fileRows)
{
foreach (var keyIndex in keyIndexes)
{
keyPair.Append(row.Substring(keyIndex.Key, keyIndex.Value));
}
dic[keyPair.ToString()] = row;
}
这是给你的一个问题...... keyPair.ToString()将在这里评估什么?
答案:您附加的所有内容的串联。它会在每次循环中增长。最终,keyPair将是一个巨大的字符串,您将其用作词典的关键字。
您的代码对我来说没有多大意义,但尝试在第一个foreach循环中移动StringBuilder创建。