Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 重构方法时内存不足_C#_Memory Leaks - Fatal编程技术网

C# 重构方法时内存不足

C# 重构方法时内存不足,c#,memory-leaks,C#,Memory Leaks,我的代码中有一些内存不足的问题,就在我将一个方法重构为更通用的方法之后,我可以用我的参数调用它。 更改前的方法会立即响应,即使它正在读取数千行,而重构后的方法会耗尽内存,看起来很沉重 private Dictionary<string, string> MapFile(string[] fileRows) { var dic = new Dictionary<string, string>(); foreach (var row i

我的代码中有一些内存不足的问题,就在我将一个方法重构为更通用的方法之后,我可以用我的参数调用它。 更改前的方法会立即响应,即使它正在读取数千行,而重构后的方法会耗尽内存,看起来很沉重

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;
    }
专用字典映射文件(字符串[]文件行)
{
var dic=新字典();
foreach(fileRows中的var行)
{
var key=row.Substring(3,10)+row.Substring(45,11);
dic[键]=行;
}
返回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;
    }
专用字典映射文件(字符串[]文件行,参数KeyValuePair[]键索引)
{
var dic=新字典();
StringBuilder键对=新建StringBuilder();
foreach(fileRows中的var行)
{
foreach(键索引中的var键索引)
{
追加(row.Substring(keyIndex.Key,keyIndex.Value));
}
dic[keyPair.ToString()]=行;
}
返回dic;
}
称之为:

 MapFile(file, new KeyValuePair<int,int>(3,10), new KeyValuePair<int,int>(45,11))
MapFile(文件,新的KeyValuePair(3,10),新的KeyValuePair(45,11))
我理解代码需要做更多的工作,但仍然不理解阅读这两种方法之间的巨大差异。一个是平滑的,响应时间不到一秒钟,另一个占用了系统的所有内存,然后崩溃

Upate:

想知道,使用Tuple作为类型来存储一对int,并与方法内的子字符串(index,length)一起使用的这个实现是否更聪明和更好

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;
    }
专用字典映射文件(字符串[]文件行,参数元组[]键索引)
{
var dic=新字典();
foreach(fileRows中的var行)
{
字符串键=”;
foreach(键索引中的var对)
{
key+=行子字符串(pair.Item1,pair.Item2);
}
dic[键]=行;
}
返回dic;
}

基本上,问题是您在每一行向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;
 }
这里有个问题要问你。。。这里keyPair.ToString()的计算结果是什么

答:您附加的所有内容的串联。每次通过循环,它都会增长。最终,keyPair将是一个巨大的字符串,您将其用作字典的键


你的代码对我来说没有多大意义,但请尝试将StringBuilder创建移动到第一个foreach循环中。

你不想在循环中使用密钥对吗,你的密钥在foreveris keyIndex中不断增长。将其本身作为一个可能会膨胀内存的字典进行估值?OP似乎在尝试重用
StringBuilder
实例。因此,将其移动到外部
foreach
中不是很有必要-添加
keyPair.Clear()就足够了。@IvanStoev我想到了,但方法就到此为止。我将添加它作为另一个解决方案,当然,更好的还是OP开始时使用的原始代码,因为它比这两个选项中的任何一个都明显更有效。非常感谢大家!看到这有多愚蠢真让人难堪。。我工作时间太长:)@Servy是肯定的,但是OP似乎出于某种原因想使用StringBuilder。谢谢Chris!这是对的,就像卡米洛提到的,只是想听听你的意见,为什么你认为代码没有意义?是的,卡米洛忍者在这一次告诉我。我不明白什么是“密钥对”,或者什么子字符串(keyIndex.Key,keyIndex.Value)让你。。。一个以键开始并且长度等于该值的子字符串似乎是一种奇怪且难以理解的使用KeyValuePair的方法。这是一种哈希算法吗?将数据行减少为行内的几个子字符串?我相信你有你的理由,但我不理解这个用例。(你不必向我解释,除非你认为这会有帮助。):)用例,通常是比较两个非常大的文件,在每个文件上,我阅读行,创建一个唯一键到此行的映射,然后在另一个文件中找到该键,并比较行。它们键映射每一行,位于每一行中,对于一个文件,位置X1长度Y1+X2长度Y2,另一个文件是H1、L1、G1+。。关键是,用于比较行的键出现在不同的索引中,因此,我不想一次又一次地调用相同的代码,而是想要一种可以提供键位置的方法。。希望我足够清楚:)
    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;
    }