简体   繁体   English

如何对以下循环进行 LINQ 化?

[英]How to LINQ-ify the following loop?

I have a method in a C# program.我在 C# 程序中有一个方法。 It enumerates all the .cs files in a certain folder and then runs through the list.它枚举某个文件夹中的所有.cs文件,然后遍历列表。 For each file, I read all the lines using File.ReadAllLines on it.对于每个文件,我使用File.ReadAllLines读取所有行。 I only want to process a file if it contains a class, whether conventional, static, or abstract, whose name begins with a certain phrase and does not end with the word Tests.我只想处理一个文件,如果它包含一个类,无论是传统的、 static,还是abstract,其名称以某个短语开头并且不以单词Tests. Moreover, I wish to find the line index in the line of lines containing the declaration of the class --- ie, the public static class Foo part.此外,我希望在包含类声明的行中找到行索引——即, public static class Foo部分。

Given that I take the result of File.ReadAllLines and call ToList() on it to create a List<string> , I wish to use the FindIndex method to find the index of the line matching my criteria (if it exists) using a Predicate.鉴于我获取File.ReadAllLines的结果并在其上调用ToList()以创建List<string> ,我希望使用FindIndex方法使用 Predicate 查找与我的条件匹配的行的索引(如果存在) .

My question is : What is a good way to write such a predicate?我的问题是:写这样一个谓词的好方法是什么?

I realize I could probably use more sophisticated methods, but I am just putting this code into a quick-and-dirty LINQPad script.我意识到我可能可以使用更复杂的方法,但我只是将这段代码放入一个快速而肮脏的LINQPad脚本中。 So, I don't have to get super fancy.所以,我不必太花哨。

Let me show you what I have so far (assume that the outermost namespace and class are already suitably declared):让我向您展示我到目前为止所拥有的(假设最外面的命名空间和类已经被适当地声明了):

void Main()
{
    var files = Directory
        .EnumerateDirectories(
            Path.Combine(
                Environment.GetFolderPath(
                    Environment.SpecialFolder.UserProfile
                ), @"source\repos\astrohart\MFR"
            ), "*", SearchOption.TopDirectoryOnly
        ).SelectMany(
            x => Directory.EnumerateFiles(
                x, "FileSystemEntry*.cs", SearchOption.AllDirectories
            )
        )
        .Where(x => !"FileSystemEntry.cs".Equals(Path.GetFileName(x)))
        .ToList();
    if (files == null || !files.Any()) return;

    foreach (var file in files)
    {
        var contents = string.Empty;

        try
        {
            contents = File.ReadAllText(file);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"ERROR: {ex.Message}");

            contents = string.Empty;
        }

        if (string.IsNullOrWhiteSpace(contents)) continue;
        if (contents.Contains("[TestFixture]")) continue;
        if (contents.Contains("[Log(AttributeExclude = true)]")) continue;

        file.Dump();

        var lines = new List<string>();
        lines.TrimExcess();

        try
        {
            lines = File.ReadAllLines(file).ToList();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"ERROR: {ex.Message}");

            lines = new List<string>();
            lines.TrimExcess();
        }

        if (lines == null || !lines.Any()) continue;

        var index = -1;

        for (var i = 0; i < lines.Count; i++)
        {
            var currentLine = lines[i].Trim();
            if (currentLine.EndsWith("Tests")) continue;

            if (currentLine.StartsWith("public static class FileSystemEntry"))
            {
                index = i;
                break;
            }
            if (currentLine.StartsWith("public class FileSystemEntry"))
            {
                index = i;
                break;
            }
            if (currentLine.StartsWith("public abstract class FileSystemEntry"))
            {
                index = i;
                break;
            }
        }

        if (index < 0) continue;
     
        /*...*/
    }
}

How do I translate the for loop in:如何翻译for循环:

var index = -1;

for (var i = 0; i < lines.Count; i++)
{
    var currentLine = lines[i].Trim();
    if (currentLine.EndsWith("Tests")) continue;

    if (currentLine.StartsWith("public static class FileSystemEntry"))
    {
        index = i;
        break;
    }
    if (currentLine.StartsWith("public class FileSystemEntry"))
    {
        index = i;
        break;
    }
    if (currentLine.StartsWith("public abstract class FileSystemEntry"))
    {
        index = i;
        break;
    }
}

if (index < 0) continue;

into a call thus:进入一个电话,因此:

var index = lines.FindIndex(currentLine => /*...*/);

I need help with how to derive the proper body of the lambda expression that matches what the for loop does.我需要有关如何派生与for循环所做的匹配的 lambda 表达式的正确主体的帮助。

Thanks in advance!提前致谢!

I havent tested this thoroughly but it seems to pass basic sanity if I compare to original code supplied above.我还没有彻底测试过,但如果我与上面提供的原始代码进行比较,它似乎通过了基本的理智。 Note that this is not best when it comes to measuring performance.请注意,在衡量性能时,这并不是最好的。 The 'foreach' loop with anonymous function has flaw that you cannot break away from the anonymous function.带有匿名函数的“foreach”循环存在无法脱离匿名函数的缺陷。 The only way to come out of a foreach is to run all foreach statements.退出 foreach 的唯一方法是运行所有 foreach 语句。 In order to preserve first index where criteria matches against line contents, I am using index in else if() comparison statement.为了保留条件与行内容匹配的第一个索引,我在 else if() 比较语句中使用索引。 This means the foreach loop will run for all lines despite of having the first occurrence of matching lines found.这意味着 foreach 循环将针对所有行运行,尽管找到了第一次出现的匹配行。

lines.ForEach((l) =>
{
    if (l.EndsWith("Tests")) ;
    else if (index ==0 && (l.StartsWith("public static class FileSystemEntry") ||
    l.StartsWith("public class FileSystemEntry") ||
    l.StartsWith("public abstract class FileSystemEntry")))
    {
        index = lines.IndexOf(l);
    }
});

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

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