帮助理解一些C#代码

时间:2010-08-10 06:03:15

标签: c#

有人可以向我解释以下方法吗?我不太明白它的作用,以及它是如何做到的。

private List<Label> CreateLabels(params string[] names)
{
    return new List<Label>(names.Select(x => new Label { ID = 0, Name = x }));
}

6 个答案:

答案 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数组中的字符串值。

这有助于解释这里发生了什么吗?