这是一个与 lambda 匹配的正则表达式,因此比常规的旧 lambda 稍微复杂一些。开始了:
鉴于:
String result = Regex.Replace(
text,
@"\[%RC:(\d+)%\]",
match => dict[int.Parse(match.Groups[1].Value)]);
(1) text - 我们正在搜索的文本。
(2) @"\[%RC:(\d+)%\]"
- 意味着找到任何看起来像“[%RC:{number}%]”的东西,其中{number}
显然是某个数字(因为\d
意味着“一个数字”,并且\d+
意味着“一个或多个连续的数字”)。还要注意{number}
or\d+
被( )
as in包围(\d+)
。这很重要,因为这意味着数字是一个“组”,这与我们下面的解释有关。组是一种从正则表达式中提取“有用”部分的方法。也就是说,我们不想要整个匹配,只想要数字值。
(3) 当它找到一个匹配时,它执行这个:match => dict[int.Parse(match.Groups[1].Value)]);
让我们从这部分开始:match => ...
,它实际上与:
public String MatchEval(Match match)
{
}
请记住,lambda 表达式本质上只是常规函数的简写(除了编译器match
根据它所代表的委托推断类型和返回类型 - 这里是MatchEvaluator - 稍后会详细介绍)。在这里,输入match
作为输入传递给 lambda 表达式。然后你就有=>
了类似于{ }
我们在MatchEval
上面的函数中看到的函数体的开头。结果,每次找到匹配项时,都会运行与此块等效的代码:
public String MatchEval(Match match)
{
// Here we grab the value from group (1) (the number in parentasis from our Regex)
return dict[int.Parse(match.Groups[1].Value)];
}
简而言之,请记住 lambda 只是函数的简写符号。如果您查看Regex.Replace的文档,您会看到 lambda 代表MatchEvaluator,其定义为:
public delegate string MatchEvaluator(Match match);
这与我们上面的功能扩展一致。事实上,你可以简单地写:
String result = Regex.Replace(
text,
@"\[%RC:(\d+)%\]",
MatchEval);
(假设dict
可以从单独的方法访问)并且该函数的工作原理与证明 lambda 只是完整函数的较短表示法相同。
编辑:
至于你的问题的第二部分,“什么是委托”,委托基本上解决了这个问题:“我不知道我想使用什么功能,但我知道它有什么签名”。考虑:
// This allows us to point to a math function with this signature,
// namely, takes two Int32 inputs, and returns an Int32.
public static delegate Int32 MathDelegate(Int32 lhs, Int32 rhs);
public static Int32 Add(Int32 lhs, Int32 rhs)
{
return lhs + rhs;
}
// Note the variable names aren't important, just their TYPE
public static Int32 Subtract(Int32 a, Int32 b)
{
return a - b;
}
static void Main()
{
// We can use a delegate to point to a "real" function
MathDelegate mathPerformer = Add;
Console.WriteLine(mathPerformer(2, 3)); // Output : 5
// Now let's point to "Subtract"
mathPerformer = Subtract;
Console.WriteLine(mathPerformer(2, 3)); // Output : -1
Console.ReadLine();
}
当您在程序已经运行之前不知道要使用什么特定算法或处理技术时,这很有用。委托让我们选择要指向的函数,然后我们可以在程序运行时执行它。
这一切都与上面的 lambda 讨论有关,MatchEvaluator
它不知道如何处理它在仔细阅读您的字符串时找到的每个匹配项。相反,通过为它提供一个 lambda/函数,你告诉它在找到匹配项时你想使用什么算法。基本上,委托对于在运行时确定您希望如何执行某些操作很有用。
编辑:如果您想扩展您的 lambda 表达式以包含多行代码,您也可以使用代码块。考虑:
String result = Regex.Replace(
text,
@"\[%RC:(\d+)%\]",
match => {
return dict[int.Parse(match.Groups[1].Value)]
});
你会注意到这里有两点不同。(1) 我们=>
现在紧随其后,{ }
它允许我们输入多行代码。结果,编译器不知道哪个值是返回值,因此无法推断返回类型是什么。因此,(2)我们插入一个显式return
命令来指示哪个值是应该返回的值。
使用这个简单的代码库,我们可以执行以下操作:
String result = Regex.Replace(
text,
@"\[%RC:(\d+)%\]",
match => {
// This does the same thing, but with more lines of code.
// Of course, you could get way more fancy with it as well.
String numericValueAsString = match.Groups[1].Value;
Int32 numericValue = Int32.Parse(numericValueAsString);
String dictionaryValue = dict[numericValue];
// Same as above
return dictionaryValue;
});