有人可以向我解释以下方法吗?我不太明白它的作用,以及它是如何做到的.
private List<Label> CreateLabels(params string[] names)
{
return new List<Label>(names.Select(x => new Label { ID = 0, Name = x }));
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 18
让我们将它分成不同的位:
private List<Label> CreateLabels(params string[] names)
Run Code Online (Sandbox Code Playgroud)
这意味着我们声明了一个返回Label引用列表的方法.我们将一个字符串引用数组作为参数,并将其声明为参数数组,这意味着调用者可以像这样指定参数:
List<Label> labels = CreateLabels("first", "second", "third");
Run Code Online (Sandbox Code Playgroud)
(或者他们可以正常传递一个字符串数组.)
现在要了解身体,我们将它分开:
IEnumerable<Labael> labels = names.Select(x => new Label { ID = 0, Name = x });
List<Label> list = new List<Label>(labels);
return list;
Run Code Online (Sandbox Code Playgroud)
第二行和第三行应该相当简单 - 它只是List<Label>从一系列标签构建一个,然后返回它.第一行可能是导致问题的那一行.
Select是泛型类型(类型的元素序列)的扩展方法,它通过以委托形式执行投影来延迟返回新序列.IEnumerable<T>T
在这种情况下,委托使用如下的lambda表达式指定:
x => new Label { ID = 0, Name = x }
Run Code Online (Sandbox Code Playgroud)
这就是说,"给定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;
Run Code Online (Sandbox Code Playgroud)
我们本可以写一个单独的方法来做到这一点:
private static Label CreateLabel(string x)
{
Label tmp = new Label();
tmp.ID = 0;
tmp.Name = x;
return tmp;
}
Run Code Online (Sandbox Code Playgroud)
然后叫:
IEnumerable<Label> labels = names.Select(CreateLabel);
Run Code Online (Sandbox Code Playgroud)
这实际上是编译器在幕后为您做的事情.
因此,投影会创建一系列标签,其名称由参数指定.然后代码从该序列创建标签列表,并返回它.
请注意,它(IMO)会更加惯用LINQ来编写:
return names.Select(x => new Label { ID = 0, Name = x }).ToList();
Run Code Online (Sandbox Code Playgroud)
而不是明确地创建List<Label>.
一般来说,编写良好的代码背后的含义通常可以由代码本身推断出来.这称为"自我记录代码".不遵循此规范的代码应该伴随着评论.
在这种情况下,您可以通过以下方式找出代码的作用:
该方法为您提供了一些关键信息:
方法的名称.这可以让您知道该方法的作用.在此示例中,调用该方法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 }));为每个名称创建一个新的Label对象,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;
Run Code Online (Sandbox Code Playgroud)
这只需要一组可变大小的名称,并将它们转换为ID设置为0的标签列表.
List<Label> labels = CreateLabels("one", "two", "three");
foreach(Label label in labels)
{
Console.WriteLine(label.Name);
Console.WriteLine(label.ID);
}
Run Code Online (Sandbox Code Playgroud)
这将打印:
一个
0
两个
0
三个
0