为什么这个函数返回什么都没有,虽然有一场比赛?什么都没、函数

2023-09-11 02:42:47 作者:曾经沧海

我调用这个(Compact Framework的 - 这code在Windows CE的手持设备上运行)方法:

 公共静态列表<字符串> GetXMLFiles(字符串的fileType,串startingDir)
{
    常量字符串延长=.XML;
    字符串目录名= startingDir;
    VAR文件名=新的名单,其中,字符串>();
    尝试
    {
        的foreach(在Directory.GetFiles串F(目录名))
        {
            字符串EXT = Path.GetExtension(F).ToUpper();
            字符串fileNameOnly = Path.GetFileNameWithoutExtension(F);
            如果((ext.Equals(续期,StringComparison.OrdinalIgnoreCase))及及(fileNameOnly.Contains(的fileType)))
            {
                fileNames.Add(F);
            }
        }
        的foreach(字符串d。在Directory.GetDirectories(目录名))
        {
            GetXMLFiles(的fileType,D);
        }
    }
    赶上(例外前)
    {
        的MessageBox.show(ex.Message);
    }
    返回的文件名;
}
 

......像这样:

 名单,其中,字符串> XMLFILES = CCRUtils.GetXMLFiles(的fileType\\);
的MessageBox.show(XMLFiles.Count.ToString());
 

...但它的返回什么(消息框显示0),即使有相匹配的文件类型与扩展名为.XML。文件

是不是因为有什么毛病我GetXMLFiles()方法?据一位猫here,我的方法是犯规了,我应该更经常加入到字符串的泛型列表(文件名)。

看书上说函数不能返回局部变量的引用,可是我试了一下却没什么问题,相关必要代码如下

如果他是对的,我不明白的是,虽然,因为在我看来,这是方法应该是如何工作的:

 (一)第一个foreach循环看下面的根文件;如果找到匹配,它添加到字符串的泛型列表
(b)第二个foreach循环,使递归调用它的方法,一旦在设备上的每个子目录;步骤a再次出现该目录,添加任何匹配字符串的泛型列表。
 

在这种方式中,所有的目录中搜索,并发现任何匹配将被添加到字符串的通用列表(文件名)。

在第二foreach循环运行的过程/处理所有的目录,控制下降到最后一行的code,返回文件名给调用者。

因此​​,根据我对它的grokking,我应该拿到赛回来了,但我发现两手空空。

如果我错了,和艾伦是正确的,在这里我应该增加附加呼叫添加/如何这种方法返工?

更新

调用它是这样的:

 名单,其中,字符串> XMLFILES = CCRUtils.GetXMLFiles(的fileType\\);
 

...不工作,但这样做:

 名单,其中,字符串> XMLFILES = CCRUtils.GetXMLFiles(的fileType,@\);
 

解决方案

在你的递归,你正在失去你的子目录中找到文件。获取返回的文件名是这样的:

 的foreach(字符串d。在Directory.GetDirectories(目录名))
{
    fileNames.AddRange(GetXMLFiles(的fileType,D));
}
 

这是怎么回事的是,此行变种的文件名=新的名单,其中,字符串>(); 创建一个称为局部变量文件名。你可能会认为,因为你的方法是静态的,在方法内部的变量是静态的。不是这种情况。因此,每次调用 GetXMLFiles ,此变量的副本为每个调用创建的。

由于文件名是本地的 GetXMLFiles 的每次调用,你需要返回给调用者所有的​​文件名是发现和调用者需要那些添加到本地是它的集合。

I am calling this (Compact Framework - this code runs on a Windows CE handheld device) method:

public static List<string> GetXMLFiles(string fileType, string startingDir)
{
    const string EXTENSION = ".XML";
    string dirName = startingDir; 
    var fileNames = new List<String>();
    try
    {
        foreach (string f in Directory.GetFiles(dirName))
        {
            string ext = Path.GetExtension(f).ToUpper();
            string fileNameOnly = Path.GetFileNameWithoutExtension(f);
            if ((ext.Equals(EXTENSION, StringComparison.OrdinalIgnoreCase)) && (fileNameOnly.Contains(fileType)))
            {
                fileNames.Add(f);
            }
        }
        foreach (string d in Directory.GetDirectories(dirName))
        {
            GetXMLFiles(fileType, d);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    return fileNames;
}

...like so:

List<String> XMLFiles = CCRUtils.GetXMLFiles(fileType, "\\");
MessageBox.Show(XMLFiles.Count.ToString());

...yet it's returning nothing (MessageBox shows "0"), even though there is a file that matches fileType and has an .xml extension.

Is it because there's something wrong with my GetXMLFiles() method? According to one cat here, my method is fouled up, and I should be adding to the generic list of string (fileNames) more often.

If he's right, I don't get that, though, because it seems to me that this is how the method should work:

(a) The first foreach loop looks at files below the root; if a match is found, it's added to the generic list of string
(b) The second foreach loop makes a recursive call to its method, once for every subdirectory on the device; step "a" occurs again for that directory, adding any matches to the generic list of string.

In this way, all directories are searched, and any matches found are added to the generic list of string (fileNames).

After the second foreach loop runs its course/handles all directories, control drops to the final line of code, which returns fileNames to the caller.

So, according to my grokking of it, I should get the match returned, but I'm getting nothing whatsoever.

If I'm wrong and Alan is right, where should I be adding the additional call to add/how should this method be reworked?

UPDATE

Calling it like this:

List<String> XMLFiles = CCRUtils.GetXMLFiles(fileType, "\\");

...doesn't work, but this way does:

List<String> XMLFiles = CCRUtils.GetXMLFiles(fileType, @"\");

解决方案

In your recursion, you are losing the files you find in the subdirectories. Capture the return filenames this way:

foreach (string d in Directory.GetDirectories(dirName))
{
    fileNames.AddRange(GetXMLFiles(fileType, d));
}

What is going on is that this line var fileNames = new List<String>(); creates a local variable called fileNames. You may think because your method is static, the variables inside the method are static. This is not the case. So, each time you call GetXMLFiles, a copy of this variable is created for each call.

Since fileNames is local to each call of GetXMLFiles, you need to return to the caller all the fileNames it finds and the caller needs to add those to the collection that is local to it.