你有编程盲点吗?
我的意思是有没有一种你无法真正习惯的通用技术或语言特性。
好吧,我有一个(或可能不止一个),我的用法是 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/