c# - 有人可以为我分解这个 lambda 表达式吗?

标签 c# .net regex string

我正在查看来自 Token Replacement and Identification 的解决方案:

string result = Regex.Replace(
    text,
    @"\[%RC:(\d+)%\]",
    match => dict[int.Parse(match.Groups[1].Value)]);

而且我不明白 MatchEvaluator 是如何重载的。

我理解一些 lambda 表达式。它接受输入 match 然后从字典中查找一个整数?

但是 match 的值从何而来? match => dict[int.Parse(match.Groups[1].Value)]); 返回的值去哪里了?

编辑:你们中的一些人提到了Delegate。令人惊讶的是,在大学学习 CS 三年后,我还没有遇到过这个词。 Delegate 是什么,它在这种特定情况下做什么?

最后编辑: 我尝试使用以下代码编写自己的委托(delegate) 我的 token 采用 [@someTokenName]

的形式
public void CreateScript(Dictionary<string,string> dictionary, string path)
    {
        //used in the regex to identify the string to replace
        var pattern = @"\[@[0-9a-fA-F]+\]";
        //read in the file found at the path
        var lines = File.ReadAllLines(path);
        int lineCounter = 0;
        foreach (string line in lines)
        {
            line = Regex.Replace(line, pattern, match => dictionary.TryGetValue((match.Groups[0].Value)));
        }

但我一直收到“无法将 lambda 表达式转换为类型‘int’,因为它不是委托(delegate)类型”。我写的那行和解决方案中找到的那行有什么区别?

最佳答案

这是一个与 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}\d+( ) 包围,如 (\d+) 中一样。这一点很重要,因为这意味着该数字是一个“组”,这与我们下面的解释有关。组是一种从正则表达式中提取“有用”部分的方法。也就是说,我们不需要整个匹配,只需要数字值

(3) 当它找到一个匹配时,它执行这个:match => dict[int.Parse(match.Groups[1].Value)]);

让我们从这部分开始:match => ...,它实际上与以下部分相同:

public String MatchEval(Match match)
{

}

请记住,lambda 表达式本质上只是常规函数的简写形式(除了编译器推断 match 的类型并且它的返回类型基于它所代表的委托(delegate) - 这里是 < strong>MatchEvaluator - 稍后会详细介绍)。此处,输入 match 作为输入传递到 lambda 表达式中。然后你有 => 开始函数体类似于我们在上面的 MatchEval 函数中看到的 { }。因此,每次找到匹配项时,都会运行与此 block 等效的代码:

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 只是完整函数的一个较短的表示法。

编辑: 至于你问题的第二部分,“什么是委托(delegate)”,委托(delegate)本质上解决了这个问题:“我不知道我想使用什么功能,但我知道它有什么签名”。考虑:

// 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();
}

当您在程序已经运行之前不知道要使用什么特定算法或处理技术时,这很有用。委托(delegate)让我们选择我们想要指向的函数,然后我们可以在程序运行时执行它。

这一切与上面的 lambda 讨论相关的方式是,MatchEvaluator 不知道如何处理它在仔细阅读您的字符串时找到的每个匹配项。相反,通过向它提供 lambda/函数,您可以告诉它在找到匹配项时要使用的算法。基本上,委托(delegate)可用于在运行时确定您希望如何执行某些操作。

编辑: 如果您想扩展您的 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;
    });

关于c# - 有人可以为我分解这个 lambda 表达式吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16677540/

相关文章:

c# - 扩展用户控制

regex - 如何阅读此命令以删除行末的所有空格

java - 正则表达式和自定义标签

c# - 从 SQLite 数据库文件检索一百万条记录并将其显示在 WPF 数据网格中的最快方法是什么?

ASP.NET:WCF 和无法加载文件或程序集“App_Web_hamznvwf”

.net - 需要一个用于从 ASP.NET 创建二进制 Excel 文件的库,有人知道一个好的库吗?

R 中仅适用于第 n 个单词的正则表达式

c# - 在 Entity Framework 中重复创建和删除数据库

c# - 使用 vbs 但不使用 C# 的 SendKey 命令

c# - 如何将 ListView 项与 UWP 模型外部的数据绑定(bind)?