简体   繁体   English

.Where出现错误,在foreach循环中使用lambda表达式处理无效参数

[英]Getting an error with .Where using a lambda expression in a foreach loop for invalid arguments

I am busy creating a file/folder indexing Windows Forms Application in VS2010(Assignment for college). 我正忙于在VS2010(大学分配)中创建索引Windows窗体应用程序的文件/文件夹。 For testing purposes the file/folder indexing class is in a console application 出于测试目的,文件/文件夹索引编制类在控制台应用程序中

I use the following to go through folders, it runs fine and writes to file all the folder names in the specified drive. 我使用以下内容浏览文件夹,它运行良好,并将所有文件夹名称写入文件指定驱动器中。 I've thrown this together from mainly the msdn resources(used the recursive method), and modified since it didn't include getting folder names. 我主要是从msdn资源(使用递归方法)将其组合在一起,并进行了修改,因为它不包含获取文件夹名称。

I want to exclude certain folders, and decided to use a lambda expression and List with list of words will be fastest, although I could just place a loop that goes through an array with an if comparison, but to my mind this would be slower(not that I understand enough about intricate workings in c#). 我想排除某些文件夹,并决定使用lambda表达式,并且带有单词列表的List将是最快的,尽管我可以通过if比较来放置遍历数组的循环,但在我看来这会比较慢(我对C#中的复杂工作还不了解。 I've had a brief look at lambda expressions to see if I can't fix it myself. 我对lambda表达式进行了简要介绍,以查看自己是否可以修复它。

Here is my code working without any folder exclusion 这是我的代码,没有任何文件夹排除在外

class Program
{
    static System.Collections.Specialized.StringCollection log = new System.Collections.Specialized.StringCollection();
    private static List<string> _excludedDirectories = new List<string>() { "Windows", "AppData", "$WINDOWS.~BT", "MSOCache", "ProgramData", "Config.Msi", "$Recycle.Bin", "Recovery", "System Volume Information", "Documents and Settings", "Perflogs" };

    //method to check
    static bool isExcluded(List<string> exludedDirList, string target)
    {
        return exludedDirList.Any(d => new DirectoryInfo(target).Name.Equals(d));
    }

    static void Main()
    {

        string[] drives = {"C:\\"};

        foreach (string dr in drives)
        {
            DriveInfo di = new System.IO.DriveInfo(dr);

            // Here we skip the drive if it is not ready to be read. 
            if (di.IsReady)
            {
                DirectoryInfo rootDir = di.RootDirectory;
                WalkDirectoryTree(rootDir);
            }
            else
            {
                Console.WriteLine("The drive {0} could not be read", di.Name);
                continue;
            }
        }

        // Write out all the files that could not be processed.
        Console.WriteLine("Files with restricted access:");
        foreach (string s in log)
        {
            Console.WriteLine(s);
        }
        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key");
        Console.ReadKey();
    }

    static void WalkDirectoryTree(System.IO.DirectoryInfo root)
    {
        FileInfo[] files = null;
        DirectoryInfo[] subDirs = null;
        StreamWriter filex = new System.IO.StreamWriter("test.txt", true);

        if (filex != null)
        {
            filex.Close();
        }

        // Process all the folders directly under the root 
        try
        {
            subDirs = root.GetDirectories();
        }// This is thrown if even one of the folders requires permissions greater than the application provides. 
        catch (UnauthorizedAccessException e)
        {
            log.Add(e.Message);
        }
        catch (System.IO.DirectoryNotFoundException e)
        {
            Console.WriteLine(e.Message);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

        // Process all the files directly under the root 
        try
        {
            files = root.GetFiles("*.*");
        }// This is thrown if even one of the files requires permissions greater than the application provides. 
        catch (UnauthorizedAccessException e)
        {
            log.Add(e.Message);
        }
        catch (System.IO.DirectoryNotFoundException e)
        {
            Console.WriteLine(e.Message);
        }
        catch(Exception e)
        {
            Console.WriteLine(e.Message);
        }

        if (files != null)
        {
            filex = new StreamWriter("test.txt", true);
            foreach (FileInfo fi in files)
            {
                // In this example, we only access the existing FileInfo object. If we 
                // want to open, delete or modify the file, then 
                // a try-catch block is required here to handle the case 
                // where the file has been deleted since the call to TraverseTree().
                Console.WriteLine(fi.FullName);
                filex.WriteLine(fi.FullName);
            }
            filex.Close();
        }

        if (subDirs != null)
        {
            //var filteredDirs = Directory.GetDirectories(root.Name).Where(d => !isExcluded(_excludedDirectories, d));
            foreach (DirectoryInfo subds in subDirs)
            {
                filex = new StreamWriter("test.txt", true);
                Console.WriteLine(subds.FullName);
                filex.WriteLine(subds.FullName);
                filex.Close();

                foreach (DirectoryInfo dirInfo in subDirs)
                {
                    // Resursive call for each subdirectory.
                    WalkDirectoryTree(dirInfo);
                }
            }
            filex.Close();// Because at end filestream needs to close
        }
    }
}

So I tried incorporating the .Where(d => !isExcluded(_excludedDirectories, d)) into my loop: 所以我尝试将.Where(d =>!isExcluded(_excludedDirectories,d))合并到我的循环中:

if (subDirs != null)
        {
            //var filteredDirs = Directory.GetDirectories(root.Name).Where(d => !isExcluded(_excludedDirectories, d));
            foreach (DirectoryInfo subds in subDirs.Where(d => !isExcluded(_excludedDirectories, d)))
            {
                filex = new StreamWriter("test.txt", true);
                Console.WriteLine(subds.FullName);
                filex.WriteLine(subds.FullName);
                filex.Close();

                foreach (DirectoryInfo dirInfo in subDirs)
                {
                    // Resursive call for each subdirectory.
                    WalkDirectoryTree(dirInfo);
                }
            }
            filex.Close();// Because at end filestream needs to close
        }

PROBLEM: I get an error from after the exclamation saying "The best overloaded method match has some invalid args..." What should I do/change, should I take the simpler route and use a loop and if statement in my loop that writes the folder names? 问题:惊叹号后出现错误,提示“最佳重载方法匹配具有一些无效的参数...”我应该做/更改,应该采用更简单的路线并使用循环,如果在循环中编写if语句文件夹名称? Because I also understand how to do that. 因为我也知道该怎么做。 And remember the way I'm currently doing(trying to at least) is because I thought it would be more optimised/faster. 并记住我目前正在做的方式(至少要尝试)是因为我认为这样会更优化/更快。 If it doesn't make such a great difference, let me know and I will use the way I know. 如果没有太大的不同,请告诉我,我将使用我所知道的方式。

My guess is that I'm doing a bad thing by trying to put a .where there in the foreach, and I realise why it is or might be. 我的猜测是,我试图通过在foreach中放置.where来做一件不好的事情,并且我意识到了为什么是或可能是。

I've also tried: 我也尝试过:

if (subDirs != null)
        {
            //var filteredDirs = Directory.GetDirectories(root.Name).Where(d => !isExcluded(_excludedDirectories, d));
            foreach (DirectoryInfo subds in subDirs)
            {
              if ((d => !isExcluded(_excludedDirectories, d)))
              {
                filex = new StreamWriter("test.txt", true);
                Console.WriteLine(subds.FullName);
                filex.WriteLine(subds.FullName);
                filex.Close();

                foreach (DirectoryInfo dirInfo in subDirs)
                {
                    // Resursive call for each subdirectory.
                    WalkDirectoryTree(dirInfo);
                }
              } 

            }
            filex.Close();// Because at end filestream needs to close
        }

but get an error about cannot convert lamba expression to type bool because it is not a delegate 但出现错误,因为它不是委托,所以无法将lamba表达式转换为bool类型

Let me know if you want to see the other code, and I will then add it, just seems a bit much. 如果您想查看其他代码,请告诉我,然后我将其添加,似乎有些过多。

d is not a string here, it's a DirectoryInfo . d在这里不是string ,而是DirectoryInfo Change your isExcluded method signature to deal with the type of d properly. 更改isExcluded方法签名以正确处理d的类型。

Your signature is: 您的签名是:

static bool isExcluded(List<string> exludedDirList, string target)

It should be: 它应该是:

static bool isExcluded(List<string> exludedDirList, DirectoryInfo target)

And your method will end up being: 您的方法最终将是:

//method to check
static bool isExcluded(List<string> exludedDirList, DirectoryInfo target)
{
    return exludedDirList.Any(d => target.Name.Equals(d));
}

The problem is here: 问题在这里:

foreach (DirectoryInfo subds in subDirs.Where(d => !isExcluded(_excludedDirectories, d)))

subDirs is of type DirectoryInfo, your isExcluded takes a string as the second argument. subDirs是DirectoryInfo类型,您的isExcluded将字符串作为第二个参数。

You want: 你要:

foreach (DirectoryInfo subds in subDirs.Where(d => !isExcluded(_excludedDirectories, d.Name)))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM