简体   繁体   English

C#Noob-将条件作为参数传递

[英]C# Noob - Passing a condition as a parameter

I already have a solution for this problem, but it seems very confusing and unpractical to me. 我已经有解决此问题的方法,但对我来说似乎混乱且不切实际。

What I intend to do is to read a file line-by-line (due to the file size, it's unpractical to load it into memory all at once), and if certain condition is met (eg: the line matches a regex pattern, or contains certain keywords, or is equal to certain string) 我打算做的是逐行读取文件(由于文件大小,一次将其全部加载到内存中是不切实际的),如果满足某些条件(例如:该行与regex模式匹配,或包含某些关键字,或等于某些字符串)

Here's what I'd Ideally have: 这是我理想的状态:

 void TryGetLineIf(string filePath, Condition condition, out string desiredLine)
  {
     StreamReader fileReader = new StreamReader(filePath);
     string currentLine = "";

     while (!fileReader.EndOfStream)
     {
        currentLine = fileReader.ReadLine();

        if (condition)
        {
           desiredLine = currentLine;
        }
     }
  }

However, I don't know what to do with the condition parameter. 但是,我不知道该如何处理condition参数。 The only way out I can think of is to replace the condition with an enum, (LineSelectionOptions.IsRegexMatch, LineSelectionOptions.ContainsString ...), add an extra parameter to the void and switch between possible values for it. 我能想到的唯一出路是用枚举替换条件(LineSelectionOptions.IsRegexMatch,LineSelectionOptions.ContainsString ...),向void添加一个额外的参数,并在可能的值之间进行切换。 I'm working with .NET 2.0, if that is relevant. 如果相关的话,我正在使用.NET 2.0。

If you know the parameters your function will have, you could use Func to pass a function which will return a bool 如果您知道函数将具有的参数,则可以使用Func传递一个函数,该函数将返回布尔值

your method definition will be like this 您的方法定义将如下所示

 void TryGetLineIf(string filePath, Func<string, bool> condition, out string desiredLine)

The if-line will be like this 如果行将是这样

if(condition(currentLine)) {
   desiredLine = currentLine;
}

and the call to the method will be something like this 对该方法的调用将是这样的

Func<string, bool> condition = (line) => line.Length > 1;
string desiredLine;
TryGetLineIf("C:\\....file.pdf", condition, out desiredLine)

BUT since you're working in 2.0, you might want to simulate Func using delegates See this How to simulate a "Func<(Of <(TResult>)>) Delegate" in .NET Framework 2.0? 但是,因为您在2.0中工作,所以您可能希望使用委托来模拟Func。请参见此方法。 如何在.NET Framework 2.0中模拟“ Func <(Of <(TResult>)>)委托”? or this Replacing Func with delegates C# 使用代理C#替换Func

Please excuse the formatting because I am on a mobile phone. 请原谅格式,因为我在用手机。

Anyhow, I think this is a perfect candidate for using yield return because the caller can decide to break and not want to read the rest of the file after any line. 无论如何,我认为这是使用yield return理想选择,因为调用者可以决定break ,而不希望在任何行之后读取文件的其余部分。 This will allow that. 这将允许。 Plus the caller can perform chaining and do further processing. 另外,调用者可以执行链接并进行进一步处理。 Furthermore, no need for an out parameter. 此外,不需要out参数。

Make sure to use the using statement and if available in .NET 2.0, use the File.ReadLines method instead: it reads line by line and it's much simpler. 确保使用using语句,如果在.NET 2.0中可用,请改用File.ReadLines方法:它逐行读取并且更加简单。 I will try and edit my answer with the suggestions I have made once I get home. 到家后,我将尝试用我提出的建议修改答案。

public static IEnumerable<string> TryGetLineIf(string filePath, Condition condition
{
     StreamReader fileReader = new StreamReader(filePath);
     string currentLine = "";

 while (!fileReader.EndOfStream)
 {
    currentLine = fileReader.ReadLine();

    if (condition.MeetsCriteria(currentLine))
    {
         yield  return currentLine;
    }

    }
} 

And as a final note it is more robust if you pass a delegate as the condition instead of a class instance as suggested in another answer. 最后要注意的是,如果您将委托作为条件而不是另一个答案中建议的类实例,则将更健壮。

@Gonzalo.- Thanks for the answer, I managed to use it in a few cases. @Gonzalo。-感谢您的回答,我设法在少数情况下使用了它。 But now I have a problem when attempting to do that with more parameters in the Func delegate, eg, when trying to check if the line matches a certain Regex pattern: 但是现在当我尝试在Func委托中使用更多参数来执行此操作时出现问题,例如,当尝试检查行是否匹配某个Regex模式时:

Func<string, string, bool> condition = 
(line, pattern) => new Regex(pattern).IsMatch(line)

IEnumerable<string> LinesIWant =
ReturnLineIf("C:\test.txt", condition);

And here's the method: 这是方法:

IEnumerable<string> ReturnLineIf(string filePath, Func<string, string, bool> condition)
{
  // (snip)
  // How do I specify a pattern when calling the method?
  if (condition(currentLine, "This should be the pattern..."))
  {
    yield return currentLine;
  }
}

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

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