有人可以向我解释以下方法吗?我不太明白它的作用,以及它是如何做到的。
private List<Label> CreateLabels(params string[] names)
{
return new List<Label>(names.Select(x => new Label { ID = 0, Name = x }));
}
答案 0 :(得分:18)
让我们把它分成不同的位:
private List<Label> CreateLabels(params string[] names)
这意味着我们声明一个返回Label
引用列表的方法。我们将一个字符串引用数组作为参数,并将其声明为参数数组,这意味着调用者可以像这样指定参数:
List<Label> labels = CreateLabels("first", "second", "third");
(或者他们可以正常传递一个字符串数组。)
现在要理解身体,我们会把它分开:
IEnumerable<Labael> labels = names.Select(x => new Label { ID = 0, Name = x });
List<Label> list = new List<Label>(labels);
return list;
第二行和第三行应该相当简单 - 它只是从一系列标签构建List<Label>
,然后返回它。第一行可能是导致问题的那一行。
Select
是泛型IEnumerable<T>
类型(类型T
的元素序列)上的扩展方法,它通过执行一个lazily返回一个新序列投影以委托的形式。
在这种情况下,委托使用 lambda 表达式指定,如下所示:
x => new Label { ID = 0, Name = x }
这就是说,“给定x
,创建一个Label
并将其ID属性设置为0,将其Name
属性设置为x
。”此处x
的类型推断为string
,因为我们在字符串数组上调用Select
。这不仅使用lambda表达式,还使用对象初始化表达式。 new Label { ID = 0, Name = x }
部分相当于:
Label tmp = new Label();
tmp.ID = 0;
tmp.Name = x;
Label result = tmp;
我们可以编写一个单独的方法来执行此操作:
private static Label CreateLabel(string x)
{
Label tmp = new Label();
tmp.ID = 0;
tmp.Name = x;
return tmp;
}
然后调用:
IEnumerable<Label> labels = names.Select(CreateLabel);
这实际上是编译器在幕后为你做的事情。
因此,投影会创建一系列带有参数指定名称的标签。然后代码从该序列创建一个标签列表,并将其返回。
请注意,它(IMO)会更加惯用LINQ编写:
return names.Select(x => new Label { ID = 0, Name = x }).ToList();
而非明确创建List<Label>
。
答案 1 :(得分:9)
一般来说,编写良好的代码背后的含义通常可以由代码本身推断出来。这称为“自我记录代码”。不遵循此规范的代码应该伴随着评论。
在这种情况下,您可以通过以下方式找出代码的作用:
该方法为您提供了一些关键信息:
方法的名称。这可以让您知道该方法的作用。在此示例中,该方法称为CreateLabels
方法的签名。这表明该方法需要什么。在此示例中,有一个类型为string的数组,其关键字为params
。关键字params
表示此方法将接受一个或多个名称作为方法的输入,并将它们收集到单个数组中。
方法的返回类型。这将告诉您希望方法在完成时给您。在此示例中,它返回标签列表。
因此,由于该方法被称为CreateLabels
,所以采用一系列名为name的字符串,并返回一个标签列表,我们可能会说“给定几个名称,此方法将返回一个列表标贴“强>
现在,如果您需要知道该方法是如何做到的,那么请查看正文。
return new List<Label>(names.Select(x => new Label { ID = 0, Name = x }));
对于不了解linq或lambda表达式的人来说,这有点难以理解。
让我们从外到内工作:
return new List<Label>()
构造一个新列表并返回新列表,并使该方法退出。
names.Select()
是一种方法,它将一组操作应用于数组中的所有对象,并返回一个新的集合,其中包含应用这些操作的结果。
x=>new Label {ID = 0, Name = x}
是一个lambda表达式,表示:x转到一个新的Label对象,其ID字段为0,Name为x
的值。
将所有内容放在一起,语句return new List<Label>(names.Select(x => new Label { ID = 0, Name = x }));
正在为names
中的每个名称创建一个新的标签对象,并将其存储到新的列表中,该列表将在方法结束时返回。
这也是一种写作方式:
List<Labels> toReturn = new List<Labels>();
foreach(string name in names)
{
Label l = new Label();
l.ID = 0;
l.Name = name;
toReturn.Add(l);
}
return toReturn;
答案 2 :(得分:6)
这只需要一组可变大小的名称,并将它们转换为ID设置为0的标签列表。
List<Label> labels = CreateLabels("one", "two", "three");
foreach(Label label in labels)
{
Console.WriteLine(label.Name);
Console.WriteLine(label.ID);
}
这将打印:
一个
0
2
0
3
0
答案 3 :(得分:3)
此代码返回List
个类的集合(Label
)。输入参数names
中的Foreach字符串变量,它创建类Label的新实例,其ID属性等于0,Name属性等于当前names
元素
您可以将此代码更改为以下内容:
private List<Label> CreateLabels(params string[] names)
{
List<Label> result = new List<Label>();
foreach(string name in names)
{
Label label = new Label()
label.ID = 0;
label.Name = name;
result.Add(label);
}
result;
}
答案 4 :(得分:1)
你需要学习这个linq 101 sample然后你就知道了这段代码的含义。
答案 5 :(得分:1)
好的,这里是:
new Label { ID = 0, Name = x }
这是创建Label
的新实例,其中ID
设置为0,Name
设置为x
。
x => new Label { ID = 0, Name = x }
这称为lambda expression - 它定义了一个匿名函数,它接受单个输入(x
)并返回一个新的label实例。您可能会发现更容易阅读x => ...
,因为“x
转到......”。
names.Select(x => new Label { ID = 0, Name = x })
这是在Select
对象上调用names
方法,将上面的lambda表达式作为参数传递。我们可以看到names
的类型是string
数组。实际上这是extension method - string[]
没有定义方法Select
,这就是Select方法(MSDN上的here)在其他地方定义的(System.Core
} assembly)
select方法只是“将序列的每个元素投影到一个新表单中”。 - 基本上它将数组中的每个元素转换为另一个对象(在我们的例子中是Label
的实例)
澄清:上述语句返回IEnumerable(一种集合)的Label
个对象,names
中每个字符串对应一个。
return new List<Label>(...);
这将返回一个新的Label
个对象列表 - 在我们的例子中,我们传入了调用Select
返回的IEnumeable。
简而言之:
此方法输出Label
个对象列表,names
中每个字符串对应一个。每个Label
对象的ID
设置为0
,其Name
设置为names
数组中的字符串值。
这有助于解释这里发生了什么吗?