-3
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

4 回答 4

7

panel1- 表单上
.controls的控件 - 添加到的控件列表panel1
.OfType<UserControl1>()- 仅属于类型UserControl1
.Select(uc => uc.combobox2)的控件 -combobox2属性(每个UserControl1(in panel1)) - 如果这些组合框的任何属性为空字符串
.Any(cb => cb.Text == String.Empty),则计算结果为 true 。Text

所以基本上如果添加到您的控件的属性的任何Text属性为空,则返回,否则。combobox2UserControl1panel1truefalse


关于.Select(uc => uc.comboxbox2).

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

关于.Any(cb => cb.Text == String.Empty)Any方法的参数与上面的相同,但是它可能会令人困惑,因为在这种情况下,“右侧”的部分=>是评估为trueor的东西false。该Any方法期望将集合中的每个项目(ComboBox在本例中为 a)转换为真或假。如果其中任何一个转换为true,它将返回 true ,否则将返回false

于 2013-02-26T16:27:49.603 回答
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(...).

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

我将使用你的代码给你一个很好的例子:

// 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 或已更改 ID 的组合框?答案是:它将是更改后的,因为在调用Select(...)时已执行ToList()

于 2013-02-26T16:24:08.457 回答
4

一个 lambda 包含三个部分。箭头“=>”,箭头左侧的参数和箭头右侧的表达式或块。

您正在使用这些 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 表达式完成的,该表达式访问并返回输入的 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 表达式生成一个返回布尔值的匿名方法。Any 使用该方法检查组合框。检查每个组合框,直到其中一个返回 true - 然后由. 返回 true Any。如果没有组合框返回 true,则返回 false Any

于 2013-02-26T16:32:10.090 回答
2

你用过 Power Shell 吗?我提出这个问题的原因本质上是 Lambda 表达式通常是管道数据。这种管道数据的方法使 Linq 的使用变得更快、更高效。这允许使用某些查询语法更快地轻松。

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

要创建 lambda 表达式,请在 lambda 运算符 => 的左侧指定输入参数(如果有),并将表达式或语句块放在另一侧。例如,lambda 表达式 x => 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 有很多了解,因为它非常重要。Lambda 表达式的另一个重要资源是O'Reily 的 C# 5.0 In A Nutshell

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

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

于 2013-02-26T16:41:28.420 回答