场景: 我正在构建一个解析浏览器信息的小软件。每个浏览器都以不同的方式表示数据,因此我想要IF语句,我必须根据浏览器提出不同的问题,但我不想用IF询问所有问题......如果......那一切都是因为它会出错。
如果用户来自FF,则问题是该页面是否包含某个字符串。如果用户来自IE,则问题是如果有100行文本。
问题是不同的,我想知道我是否可以从我正在编码的函数外部发送语句来解析来自所有浏览器的信息,或者我必须问问题取决于浏览器?
答案 0 :(得分:4)
您可以将谓词中必须包含的条件封装起来,然后将其传递给执行实际测试的方法。
例如,假设如果某个条件成立,此方法会使用字符串执行某些操作,但您不希望硬编码该条件的确切内容。你可以这样写:
void PerhapsDoSomething(string input, Func<string, bool> predicate)
{
if (predicate(input))
{
Console.WriteLine("I did something.");
}
}
并像这样使用它:
// Do something if input length > 2
PerhapsDoSomething("foo", s => s.Length > 2);
或者像这样:
// Do something if input ends with "bar"
PerhapsDoSomething("foo", s => s.EndsWith("bar"));
谓词(这是一个逻辑术语,不要与委托类型Predicate<T>
混淆,虽然当然Predicate<T>
是谓词)也可以利用范围内的其他信息当它通过捕获变量定义时 - 阅读anonymous methods。
当然,这不会让你摆脱谓词的条件选择,因为你仍然必须在某个地方这样做:
Func<string, bool> predicate;
if (/* is Firefox */) predicate = s => s.Length > 2;
else if (/* is Chrome */) predicate = s => s.EndsWith("bar");
然而,它允许你移动你的通用功能之外的条件,不需要知道任何关于浏览器及其差异的信息,而是更合适的位置。
答案 1 :(得分:1)
您可以使用Func<>
谓词将部分代码发送到方法中:
private void Parse(string data, Func<string, bool> question) {
if (question(data)) {
// go on
}
}
您可以使用与签名匹配的功能调用它,例如:
private bool CheckFx(string data) {
return data.IndexOf("Hello") != -1;
}
Parse(data, CheckFx);
或:
Parse(data, s => s.Split(Environment.Newline).Length >= 100);
您还可以在选择要使用的内容时将谓词保留在变量中:
Func<string, bool> question;
switch (browser) {
case Browser.IE: question = CheckIE; break;
case Browser.Fx: question = CheckFx; break;
default: question = CheckOther; break;
}
Parse(data, question);