C# – 使用lambda表达式或LINQ填充列表

已经有一段时间了,因为我已经使用了lambda表达式或LINQ,并且想知道如何使用这两种方法执行以下操作(我知道我可以使用foreach循环,这只是出于好奇)。

我有一个字符串路径数组(如果这是一个数组或列表,它会有所不同吗?)我想从中返回一个只有文件名的新列表。

即使用foreach循环,它将是:

string[] paths = getPaths(); List listToReturn = new List(); foreach (string path in paths) { listToReturn.add(Path.GetFileName(path)); } return listToReturn; 

我如何用lambda和LINQ做同样的事情?

编辑:在我的情况下,我使用返回的列表作为ListBox(WPF)的ItemsSource所以我假设它将需要是一个列表而不是IEnumerable?

您的主要工具是.Select()方法。

 string[] paths = getPaths(); var fileNames = paths.Select(p => Path.GetFileName(p)); 

如果这是一个数组或列表,它会有所作为吗?

不,数组也实现IEnumerable


请注意,这种最小化方法涉及延迟执行 ,这意味着fileNames是一个IEnumerable ,只有当您从中获取元素时才开始迭代源数组。

如果你想要一个List(为了安全),请使用

 string[] paths = getPaths(); var fileNames = paths.Select(p => Path.GetFileName(p)).ToList(); 

但是当有许多文件时,您可能希望通过使用延迟执行源来反向(使结果交错,更快):

 var filePaths = Directory.EnumerateFiles(...); // requires Fx4 var fileNames = filePaths.Select(p => Path.GetFileName(p)); 

这取决于你接下来要用fileNames做什么。

我认为“LINQ”你的意思是“查询表达式”,但是:

 // Query expression var listToReturn = (from path in paths select Path.GetFileName(path)).ToList(); // Extension methods and a lambda var listToReturn = paths.Select(path => Path.GetFileName(path)) .ToList(); // Extension methods and a method group conversion var listToReturn = paths.Select(Path.GetFileName) .ToList(); 

通过从方法组构造投影委托来注意最后一个如何工作,如下所示:

 Func projection = Path.GetFileName; var listToReturn = paths.Select(projection).ToList(); 

(以防万一不清楚。)

请注意, 如果您不需要将其用作列表 – 如果您只想迭代它,换句话说 – 您可以从这些方法中删除ToList()调用。

只是:

 var listToReturn = getPaths().Select(x => Path.GetFileName(x)).ToList(); 

正如在其他答案中已经说明的那样,如果你实际上不需要List你可以省略ToList()并简单地返回IEnumerable (例如,如果你只需要迭代它, IEnumerable<>更好,因为避免创建其他字符串列表)

此外,假设Select()方法接受委托,并且方法组和具有相同签名的委托之间存在隐式转换,则可以跳过lambda并执行以下操作:

 getPaths().Select(Path.GetFileName) 

你可以这样做:

 return getPaths().Select(Path.GetFileName); 
 listToReturn = paths.ToList().Select(p => Path.GetFileName(p));