AddRange()方法是否应该返回一个列表?

4
在以下代码中:
var cats = new List<string>() {"cat1", "cat2"};
var dogs = new List<string>() {"dog1", "dog2"};

var animals = new List<Animal>();

animals = (cats.Select(x => new Animal() {Type = "Cat", Name = x}).ToList().AddRange(
                        dogs.Select(x => new Animal() {Type = "Dog", Name = x}).ToList())).ToList();

在结尾处调用ToList()是错误的,因为AddRange()返回void。当使用Linq类型查询时,这似乎不正确。
我发现我可以将其更改为.Union()或.Concat()来解决此问题,但是AddRange()应该被更新吗?还是它返回void有原因?

4
通常情况下,查询 不会修改数据源,它仅会返回数据。 - Lasse V. Karlsen
2
请注意,您使用的不是典型的LINQ语法。是的,您使用了LINQ,但您将代码“流畅地”结构化,这略有不同。您正在说,构建一个列表,然后向其中添加一些内容。虽然您使用LINQ来构建第一个列表和要添加到其中的内容,但这并不完全是LINQ。 - Lasse V. Karlsen
4个回答

6

AddRange改变了基础的List对象,没有任何LinQ方法会这样做。因此,它在本质上是不同的,不应该在LinQ连接中使用。其返回值void反映了这一点。


将更改和查询放在同一行的原因是我正在创建的周围 Linq 表达式的上下文(未显示)。我已经将其更改为使用 Concat,但我知道将这两个操作分开以保持代码更清晰是更好的做法。 - finoutlook

5

你已经回答了自己的问题。如果你想从两个列表中获取不同的值,请使用Union;如果你只想将两个列表连接起来,请使用Concat。一旦这两个可枚举对象被连接,你可以调用ToList()。

AddRange是List本身的一个方法,与LINQ无关。


3

针对你的情况,最好使用Enumerable.Concat

animals = cats.Select(x => new Animal() {Type = "Cat", Name = x})
                .Concat(dogs.Select(x => new Animal() {Type = "Dog", Name = x})).ToList();

你可能只需要在这里使用 Concat,而不是 Union,因为没有必要明确地删除重复项。 - Servy
谢谢,我现在已经改用Concat了,但我只是想知道为什么AddRange不适合。 - finoutlook

3
AddRangeList<T>上的一个方法,早于LINQ。它在原地更改当前列表,因此不需要返回它(也不遵循当今流行的流畅语法风格)。List<T>不是不可变的,因此可变方法调用是可以的。
有一些LINQ方法可以将列表连接在一起(就像您在问题中提到的)。我倾向于不要将更改操作嵌入到LINQ方法链中,因为它违反了LINQ仅仅是一个查询/投影设置而不“更新”事物的一般思想。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接