为什么在 List<T> 中使用 Linq 的 Prepend() 方法无法正常工作?

8
问题在于我尝试在列表的开头添加一个对象,但结果发现这个对象根本没有被添加到列表中。我的代码如下:
List<string> names = GetNames();
string defaultName = "default";
if (!names.Contains(defaultName))
    names.Prepend(defaultName);

有趣的是,当我调试代码时,Prepend()指令已经执行了,但是没有任何反应。因此,我不得不使用List.Insert()来完成任务,但我不明白这里发生了什么?
我的名字列表只是一个包含4个名称的简单列表,没有什么特别的,我正在使用Visual Studio 2017和.NET Framework 4.7,如果有帮助的话。

2
LINQ 操作将其输入视为不可变;您需要使用返回值。尝试 names = names.Prepend(defaultName); - John Wu
LINQ 不会修改源,而且您没有使用 Prepend 的结果。 - Slai
1
原始的 List 不会被改变。它返回一个以请求的元素开头的 IEnumerable。在文档中写得非常清楚 https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.prepend?view=netframework-4.7.2#remarks - Ofir Winegarten
1个回答

13
正如评论中的人们已经提到的,Prepend不会修改源,并且Enumerable类中的所有扩展方法都适用于此。 另外,在文档中也提到了

该方法不会修改集合的元素。相反,它创建一个包含新元素的集合副本。

解决方案是存储从Prepend返回的值,而不是丢弃它。
此外,如果您想要找到实际修改源的方法,则使用Insert,否则您还可以创建自己的Prepend扩展方法:
static class Extentions
{
    public static void Prepend<T>(this List<T> source, T element) => source.Insert(0, element);
}

你可以像使用Enumerable.Prepend一样使用此方法,但是必须确保你的代码实际上调用的是这个版本的Prepend而不是Enumerable类中的那个。
如果合适的话,你可以通过将Prepend重命名为PrependToList来完全消除混淆。

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