c# - 为什么内联方法不等同于显式声明它?

标签 c# delegates c#-2.0 inline

你有编程盲点吗?

我的意思是有没有一种你无法真正习惯的通用技术或语言特性。 好吧,我有一个(或可能不止一个),我的用法是 delegate . 举手!还有谁对委托(delegate)感到不自在?说实话!

那么什么是委托(delegate)?

自从我在大学的类(class)向我介绍了 C,我了解了函数指针。 如果您想将方法作为参数传递,函数指针会很方便。 所以在我看来,委托(delegate)就像一个函数指针。 Eureka !我得到了它。我没有!

具体场景?

我想从文本文件中删除与 regular expression 匹配的任何行. 假设我有一组线条,List<T>有方法RemoveAll这似乎非常适合这个目的。 RemoveAll需要一个评估方法作为决定是否删除或保留列表元素的参数。 就是这样:函数指针!

这里有代码吗?

public static int RemoveLinesFromFile(string path, string pattern)
{
  List<string> lines = new List<string>(File.ReadAllLines(path));
  int result = lines.RemoveAll(DoesLineMatch);
  File.WriteAllLines(path, lines.ToArray());
  return result;
}

所以我正在寻找一个函数 DoesLineMatch它评估一行是否与模式匹配。

你看到问题了吗?

RemoveAll期待一位委托(delegate) Predicate<string> match作为论据。 我会这样编码:

private static bool DoesLineMatch(string line, string pattern)
{
  return Regex.IsMatch(line, pattern);
}

但随后我收到错误消息“需要一个带有‘bool DoesLineMatch(string)’签名的方法”。 我在这里缺少什么?

它是否有效?

这就是我最终让它工作的方式:

public static int RemoveLinesFromFile(string path, string pattern)
{
  List<string> lines = new List<string>(File.ReadAllLines(path));
  int result = lines.RemoveAll(delegate(string line)
    {
      return Regex.IsMatch(line, pattern);
    });
  File.WriteAllLines(path, lines.ToArray());
  return result;
}

我很高兴它有效,但我不明白。

问题是什么?

为了让它工作,我所做的只是简单地内联该方法。 据我了解内联,它只是某种使用一次并销毁的代码。 如果您只使用一次变量或方法,则可以内联它,但内联始终等同于显式声明它。

有没有办法显式声明方法?我该怎么做?

PS.: 请原谅我的问题有点冗长。

PPS.:一旦我得到这个委托(delegate)的东西,我就会从 2.0 飞跃到 3.0 并学习 lambdas。

PPPS.: 关注Jon's hint关于 Regex.IsMatch(string, string) 的效率我修改了我的代码:

  int result = lines.RemoveAll(delegate(string line)
    {
      Regex regex = new Regex(pattern);
      return regex.IsMatch(line);
    });

这对效率问题没有多大帮助。所以我关注了ReSharper的提案并将 Regex 实例移到外部范围:

  Regex regex = new Regex(pattern);
  int result = lines.RemoveAll(delegate(string line)
    {
      return regex.IsMatch(line);
    });

现在 ReSharper 敦促我用方法组替换它:

  Regex regex = new Regex(pattern);
  int result = lines.RemoveAll(regex.IsMatch);

这与此处提出的答案非常相似。不是我要求的,但我再次对 ReSharper(当然还有 Stack Overflow)如何帮助学习感到惊讶。

最佳答案

您正在尝试使用具有以下签名的方法:

bool DoesLineMatch(string line, string pattern)

对于有签名的委托(delegate):

bool Predicate(string value)

它会从哪里获得第二个字符串值(模式)?

用显式声明的方法做到这一点的唯一方法是这样的:

public sealed class RegexHolder
{
    private readonly string pattern;

    public RegexHolder(string pattern)
    {
        this.pattern = pattern;
    }

    public bool DoesLineMatch(string line)
    {
        return Regex.IsMatch(line, pattern);
    }
}

然后:

public static int RemoveLinesFromFile(string path, string pattern)
{
    List<string> lines = new List<string>(File.ReadAllLines(path));
    RegexHolder holder = new RegexHolder(pattern);
    int result = lines.RemoveAll(holder.DoesLineMatch);
    File.WriteAllLines(path, lines.ToArray());
    return result;
}

这与编译器使用匿名方法为您所做的很接近 - 它将创建一个嵌套类来保存捕获的变量(在本例中为pattern)。

(请注意,我避免讨论调用 Regex.Match(string, string) 而不是创建 Regex 的单个实例的效率。 .那是另一回事。)

关于c# - 为什么内联方法不等同于显式声明它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1508774/

相关文章:

c# - 如何验证 documentdb 存储过程 REST 调用

c# - 无法从 NHibernate.Driver.OracleDataClientDriver 创建驱动程序(复制本地设置为 true)

c# - 获取 xUnit 解决方案目录路径

c# - Cast Interface 到它的实现

c# - 如何在 C# 中创建 lua 样式的函数表?

具有通用返回类型列表的 C# 委托(delegate)

iphone - 如何获取有关 imageWithContentsOfFile : completion? 的通知

c# - 检查两个列表中相同的元素

c# - 有关硬件 ID 的帮助

c# - C#中如何在WebBrowser控件中加载本地HTML页面