了解lambda表达式的工作原理

时间:2013-02-26 16:20:46

标签: c# lambda

Regex regex = new Regex("^[a-zA-Z0-9,-_ ]{2,12}$");
            return panel1.Controls.OfType<UserControl1>()
.Select(uc => uc.comboBox2).Any(cb => cb.Text == String.Empty);

因为代码用于验证我正在实现这个但我不知道它是如何工作的以及它在哪里流动。任何人都可以帮我理解这一行吗?

return panel1.Controls.OfType<UserControl1>()
.Select(uc => uc.comboBox2).Any(cb => cb.Text == String.Empty);

4 个答案:

答案 0 :(得分:7)

panel1 - 您表单上的控件
.controls - 添加到panel1的控件列表
.OfType<UserControl1>() - 仅限UserControl1类型的控件 .Select(uc => uc.combobox2) - combobox2属性(每个UserControl1panel1)) .Any(cb => cb.Text == String.Empty) - 如果这些comboxbox的Text属性中的任何一个是空字符串,则求值为true。

所以基本上,如果添加到Text控件的combobox2 UserControl1属性的panel1属性为空,则返回{{1} },否则true


关于false的一些解释。

这就是说调用集合.Select(uc => uc.comboxbox2)中的每个项目。对于每个uc,返回uc右侧创建的值。在那种情况下,它是=>。想象一下,只做一个,你得到一个uc.combobox2类型的变量(我猜)。因为这是ComboBox方法的上下文,我们将为每个项目执行此操作。对所有人进行此操作意味着您可以根据您的Select集合收集它们。

关于UserControl1 .Any(cb => cb.Text == String.Empty)方法的参数与上面的相同,但它可能会令人困惑,因为“Any”右侧的部分在此情况下评估为=>truefalse方法需要将集合中的每个项目(在本例中为Any)转换为true或false。如果其中任何一个转换为ComboBox,它将返回true,如果没有,则返回true

答案 1 :(得分:5)

  • .Select(...)迭代给定集合中的所有项目,并将新集合投影为IEnumerable<T>,其中项目是所选属性或任何对象。

  • .Any(...)迭代投影集合中的所有项目,并检查至少有一个项目是否满足布尔条件。

更新

Select(...)Any(...)都有一个lambda表达式作为输入参数。在C#中:

uc => uc.comboBox2 

...等同于(还有其他变体):

delegate(UserControl1 uc) { return uc.comboBox2; }

......和:

cb => cb.Text == String.Empty

......相当于:

delegate(ComboBox cb) { return cb.Text == String.Empty }

实际上,除了表达式树之外,lambda表达式只是具有更多函数式编程语法的委托。

延期执行

作为旁注,代码中有一个重点:Select不会执行(列表,集合:任何实现IEnumerable<T>的内容),直到它被迭代。也就是说,执行foreach,调用.ToList() / .ToArray()或您的案例:.Any(...)

这很重要,因为当整个枚举枚举时,作为延迟执行一部分的对象可能会处于无效状态。

我将使用您的代码为您提供一个很好的示例:

// First of all we select the combo boxes identifiers:
var selectedItems = panel1.Controls.OfType<UserControl1>()
.Select(uc => uc.comboBox2.ID);

// Then we get the first combobox and we change its identifier:
var firstCombo = panel1.Controls.OfType<UserControl1>().First().comboBox2;
firstCombo.comboBox2.ID = "ChangedID";

// Now we convert the selectedItems to a list with ToList():
List<string> list = selectedItems.ToList();

组合框ID列表的第一项是否具有包含原始ID或更改后的第一个组合框?答案是:它将是已更改的,因为Select(...)在调用ToList()时执行了!

答案 2 :(得分:4)

lambda有三个部分。箭头“=&gt;”,箭头左侧的参数和箭头右侧的表达式或块。

您正在使用这些lambdas来创建匿名方法。 Lambdas也可用于创建表达式树,但我不会在这里进行说明。

此方法调用Select将每个输入项目投射到输出中:

//use the expression syntax, which implies that the value of the expression is returned.
// creates an anonymous method.
Select(uc => uc.comboBox2)

这是通过lambda的表达式来完成的,lambda访问并返回输入的combobox2属性的值。这段代码做了同样的事情:

//use the block syntax to create an anonymous method.
Select(uc => { return uc.comboBox2; })

如果您不喜欢lambda,只要方法的签名与您调用的方法的参数匹配,就可以使用您定义的方法。

//define a method yourself.
public ComboBox GetComboBox(UserControl1 uc)
{
  return uc.combobox2;
}

//use that method in the Select call.
Select(GetComboBox)

此方法调用Any枚举源并在找到符合条件的第一个项目时停止,返回true。如果在未找到匹配项的情况下到达结尾,则Any将返回false。

 Any(cb => cb.Text == String.Empty);

lambda表达式生成一个返回bool的匿名方法。任何使用该方法来检查Comboboxes。检查每个组合框直到一个返回true - 然后Any返回true。如果没有组合框返回true,则Any返回false。

答案 3 :(得分:2)

你曾经使用过Power Shell吗?我提出这个问题的原因主要是Lambda Expression是通常管道数据。这种管道数据的方法允许Linq的使用明显更快,更有效。这允许使用某些查询语法更快轻松。

  

lambda表达式是您可以使用的匿名函数   创建委托或表达式树类型。通过使用lambda   表达式,您可以编写可以作为传递的本地函数   参数或作为函数调用的值返回。 LAMBDA   表达式对于编写LINQ查询特别有用   表达式。

     

要创建lambda表达式,请指定输入参数(如果有)   在lambda operator =&gt;的左侧,你放了表达式   或另一方的声明块。例如,lambda   表达式x =&gt; x * x指定一个名为x并返回的参数   x平方的值。您可以将此表达式分配给委托   类型,如以下示例所示:

delegate int del(int i);
static void Main(string[] args)
{
    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25
}

关于Lambda表达式的注意事项是=>运算符。它具有与=的赋值相同的优先级,并且是一个右关联。

Microsoft Developer Network在Lambda上有很多,因为它非常important。 Lambda Expressions的另一个重要资源是O'Reily的 C#5.0 In A Nutshell

在您的情况下,Lambda说明:如果您的任何用户控制字段为空,则返回true。否则它将返回false。这是使用正则表达式和Lambda表达式错误检查字段的有效方法。

@George Duckett还会详细介绍您的代码含义。