2

首先,我对 LINQ 和 lambda 表达式有一种莫名的好感 :)
所以我使用 LINQ 编写了一个非常简单的代码,它应该根据特定的名称模式从目录中获取文件,对它们进行排序并累积直到总长度累积文件超过某个阈值:

IEnumerable<FileInfo> l_allFiles = new DirectoryInfo(l_sDirName).GetFiles().Where(l_fileInfo => ms_pattern.IsMatch(l_fileInfo.Name)).OrderBy(l_fileInfo => l_fileInfo.CreationTime);
int l_nFilesTotal = l_allFiles.Count();
if (nFilesTotal > 0)
{
    long l_nAccumulatedCmdLength = 0;
    IEnumerable<FileInfo> l_selectedFiles = l_allFiles.TakeWhile(l_fileInfo => (l_nAccumulatedCmdLength += l_fileInfo.Length) <= Settings.Default.Threshold);

    int l_nNumOfSelected = l_selectedFiles.Count();
    if (l_nNumOfSelected > 0)
    {
        l_ret = new A { Files = l_selectedFiles };
    }
}


好吧,当所有找到的文件一起不超过阈值时,此代码可以正常工作。
只要不是所有找到的文件都被选中l_selectedFiles,在大多数情况下,即使不是空的,也会l_selectedFiles.Count()返回0 。l_selectedFiles在极少数情况下,当返回正确的值时, A类中l_selectedFiles.Count()的连续调用会返回0。 更令人费解的是,调试器始终不是在方法执行后更新值,而是在执行下一条语句后更新。在没有选择所有文件的情况下,值并不总是如预期 的那样......为了完成图片,我使用Microsoft Visual Studio 2010 Ultimate onFiles.Count()
l_nAccumulatedLengthTakeWhile()l_selectedFiles.Count()l_nAccumulatedLength
Windows 7 Professional和我的项目的目标是.NET4.0

任何人都可以对这种行为和/或如何解决它给出解释或提示吗?因为我很迷茫,甚至无法想象我是如何调试和解决这个问题的,而社区是我最后的希望。

提前感谢大家的回复和评论。

4

1 回答 1

3

您正在修改查询中的变量:

long l_nAccumulatedCmdLength = 0;
IEnumerable<FileInfo> l_selectedFiles = l_allFiles
     .TakeWhile(l_fileInfo => (l_nAccumulatedCmdLength += l_fileInfo.Length) <=
                                   Settings.Default.Threshold);

请注意l_nAccumulatedCmdLength您的TakeWhile条件范围内的变化。

这是一个非常糟糕的主意,每次评估时序列都会给出不同的结果。只是不要这样做。我强烈怀疑这是问题的原因。

注意这部分:

更神秘的是,调试器总是更新 l_nAccumulatedLength 的值,而不是在执行 TakeWhile() 方法之后,而是在执行下一个 l_selectedFiles.Count() 语句之后。

...很容易解释。TakeWhile不会迭代序列 - 它只是构建一个新序列,该序列将被延迟评估。

如果您想获得一致的结果,请使用ToList... 但最好不要一开始就修改查询中的变量。如果需要,用于Aggregate创建值序列,Tuple<FileInfo, long>其中long值是“到目前为止的大小”。

于 2012-08-17T21:57:56.390 回答