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

本文关键字:lambda 表达式 分解 | 更新日期: 2023-09-27 18:14:35

>我正在查看令牌替换和识别的解决方案:

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是什么,在这种特定情况下它有什么作用?

上次编辑:我尝试使用以下代码编写自己的委托我的代币以[@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',因为它不是委托类型。我写的行和解决方案中找到的行有什么区别?

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

这是一个与 lambda 匹配的正则表达式,因此比常规的旧 lambda 复杂一些。来吧:

鉴于:

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

(1( 文本 - 我们正在搜索的文本。

(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 的类型,并且它的返回类型基于它所代表的委托 - 这里是 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.Rereplace 的文档,您会发现 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;
    });

想象一下:

string result = Regex.Replace(
text,
@"'[%RC:('d+)%']",
lambda);
//public delegate string MatchEvaluator(Match match)
string lambda(Match match) {
   return dict[int.Parse(match.Groups[1].Value)]); 
}

lambda 表达式与 MatchEvaluator 的类型相同:match 的值来自正则表达式(就像 lambda 表达式被定义为常规委托一样(,并且 lambda 表达式返回的值被分配给result,同样,就像它被定义为常规委托一样。

用简单的英语:

对于表达式匹配的所有组,在 1 值的索引处使用该组,将该值解析为int,并将其用作索引器/键,以从名为 dictdictionary object中提取值以用作替换新值。

lambda 只是匿名函数,它使用匹配项作为参数并在参数上下文中执行主体。

lambda 只是定义一个匿名函数。 该函数将传递给 Replace 方法(在本例中(。 然后,Replace可以用这种方法做任何它想做的事情。 您需要检查该特定方法的文档,以了解它如何使用提供的委托;您需要依靠它来告诉您参数的来源,它与返回值的作用等。

该方法的 MSDN 页指出,作为该参数的说明:

一种自定义方法,用于检查每个匹配项并返回原始匹配的字符串或替换字符串。

因此我们知道,对于找到的每个匹配项,

它将调用此方法,将表示找到的匹配项的 Match 对象作为参数传递。 然后,它将使用该方法的string返回值(我知道它是一个字符串,因为该委托的定义是这样声明的(作为替换找到的匹配项的内容。