将for循环转换为linq查询

本文关键字:linq 查询 转换 for 循环 | 更新日期: 2023-09-27 18:02:52

我喜欢认为自己很擅长使用LINQ,但有时我试图完成一些我无法开始工作的事情。我想将SPListItemCollection转换为字典,这样我就可以使用键来查找值,而不需要每次进行LINQ查询:

var formsConfigItems = new Dictionary<string, string>();
foreach (SPListItem item in list.GetItems(query))
    formsConfigItems.Add(item.Title, (item["Value"] == null ? string.Empty : item["Value"].ToString()));

这是可行的,但我希望用一种更简洁的方式,使用LINQ。(这没什么大不了的,但我喜欢尽可能使用LINQ而不是for循环,尽管在幕后是一样的。)

我试着这样做:

var formsConfigItems = (from SPListItem i in list.GetItems(query)
                        select new { i.Title, i["Value"].ToString() }).ToDictionary<string, string>(k=>k.Key, k=>k.Value);

但这似乎不起作用。如果我尝试在list.GetItems(query)上使用lambda表达式,我没有选择使用.Where或任何LINQ命令(这很奇怪,因为它是SPListCollection)

将for循环转换为linq查询

尝试:

var formsConfigItems = list.GetItems(query)
                           .Cast<SPListItem>()
                           .ToDictionary(item => item.Title, 
                                         item => Convert.ToString(item["Value"]));

回答您的问题:

如果我尝试在list.GetItems(query)上使用lambda表达式,我不是给出了使用.Where或任何linq命令的选项(这很奇怪)因为它是一个SPListCollection)

这是因为SPListCollection是一个"老派"集合,实现了IEnumerable而不是IEnumerable<T>,所以c#/LINQ(无论如何在编译时)无法告诉它包含的类型项。Cast<SPListItem>()调用有助于解决这个问题——它将IEnumerable转换为IEnumerable<T>,从而允许在编译时进行类型代数运算。您的for循环没有这个问题,因为您显式地指定了循环变量的类型—编译器代表您为序列中的每个项目插入强制转换。

我试图做这样的事情(查询表达式)。但这似乎行不通。

这是因为您没有正确地构造匿名类型实例(不能为任意表达式推断属性名称),并且您的lambda表达式也不完全正确(您使用的属性名称与匿名类型的属性名称不匹配)。试试这个:

var formsConfigItems = (from SPListItem i in list.GetItems(query)
                        select new 
                        { 
                            i.Title, 
                            Value = Convert.ToString(i["Value"])
                        }).ToDictionary(a => a.Title, a => a.Value);

我有更好的解决方案,但是你还缺少另一件事:你的LINQ语句正在创建一个匿名项目的集合,但是你没有给匿名类中的属性命名。

k=>k.Key表达式不起作用,因为它不知道Key是什么——你只定义了Title(因为你没有给它一个名字,它从对象中借用了一个名字)。Value不能自动计算出来,所以它会抛出一个编译错误。

要这样做,您需要特别声明名称:

new { Key = i.Title, Value = i["Value"].ToString() }