【问题标题】:C# Noob - Passing a condition as a parameterC# Noob - 将条件作为参数传递
【发布时间】:2017-07-21 14:22:22
【问题描述】:

我已经有了解决这个问题的方法,但对我来说似乎非常令人困惑和不切实际。

我打算做的是逐行读取文件(由于文件大小,一次将其全部加载到内存中是不切实际的),并且如果满足某些条件(例如:该行匹配正则表达式模式,或包含某些关键字,或等于某个字符串)

这是我最理想的:

 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;
        }
     }
  }

但是,我不知道如何处理条件参数。我能想到的唯一方法是用枚举(LineSelectionOptions.IsRegexMatch,LineSelectionOptions.ContainsString ...)替换条件,向void添加一个额外的参数并在它的可能值之间切换。如果相关,我正在使用 .NET 2.0。

【问题讨论】:

  • 你的意思是你不知道如何处理这个条件?不知道条件的逻辑怎么写?
  • 是的。我不知道如何使条件检查当前正在读取的行(在文件中)是否满足“选择”的标准
  • @Gonzalo.- 不确定你是否能在下面看到我的回复,所以我也在这里标记你

标签: c# .net .net-2.0


【解决方案1】:

如果您知道您的函数将具有的参数,您可以使用Func 传递一个返回布尔值的函数

你的方法定义是这样的

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

if-line 会是这样的

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

对方法的调用将是这样的

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

但是由于您使用的是 2.0,您可能希望使用委托来模拟 Func 请参阅此How to simulate a "Func<(Of <(TResult>)>) Delegate" in .NET Framework 2.0? 或此Replacing Func with delegates C#

【讨论】:

  • 值得在您的帖子中添加执行此操作的代码 - public delegate T Func&lt;T, T2&gt;(T2 arg); - 但也许还可以解释如何使用强类型委托来执行此操作...
  • 你真的需要Func&lt;string, bool&gt; condition = (line) =&gt; line.Length &gt; 1; 因为var condition = (line) =&gt; line.Length &gt; 1; 不能编译。
  • 对不起,我这里没有VS,所以我是靠记忆做的(或试图用var lol保存)
  • 无论如何都不需要使用委托来模拟Func&lt;T, TResult&gt;,因为它是一个委托:D OP 可以将委托声明为他/她自己的解决方案的一部分:public delegate TResult Func&lt;T, TResult&gt;(T input);... 稍后制作我们如下:new Func&lt;string, bool&gt;(delegate(line) { return line.Length &gt; 1; });.
【解决方案2】:

由于我在手机上,请原谅格式。

无论如何,我认为这是使用yield return 的完美候选,因为调用者可以决定使用break 并且不想在任何行之后读取文件的其余部分。这将允许这样做。另外,调用者可以执行链接并进行进一步处理。此外,不需要out 参数。

确保使用using 语句,如果在.NET 2.0 中可用,请改用File.ReadLines 方法:它逐行读取,而且更简单。回到家后,我将尝试使用我提出的建议来编辑我的答案。

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;
    }

    }
} 

最后一点,如果您将委托作为条件而不是另一个答案中建议的类实例,则它会更加健壮。

【讨论】:

    【解决方案3】:

    @Gonzalo.- 感谢您的回答,我设法在少数情况下使用它。但是现在我在尝试使用 Func 委托中的更多参数时遇到了问题,例如,当尝试检查该行是否与某个正则表达式模式匹配时:

    Func<string, string, bool> condition = 
    (line, pattern) => new Regex(pattern).IsMatch(line)
    
    IEnumerable<string> LinesIWant =
    ReturnLineIf("C:\test.txt", condition);
    

    方法如下:

    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;
      }
    }
    

    【讨论】:

    • 我现在不明白你的问题。也许您应该更新原始问题,在底部添加新信息,而不是将其作为答案发布
    猜你喜欢
    • 2011-11-02
    • 1970-01-01
    • 2011-03-20
    • 2013-01-16
    • 2015-04-12
    • 2011-07-27
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多