1

我喜欢认为自己在 LINQ 方面做得很好,但我时不时地尝试完成一些我无法开始工作的事情。我想将 a 转换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 以更简洁的方式做到这一点。(没什么大不了的,但我喜欢尽可能在 for 循环上使用 LINQ,尽管它在幕后是一样的。

我试图做这样的事情:

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);

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

提前致谢。

4

2 回答 2

7

尝试:

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

回答您的疑问:

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

那是因为它是一个实现但没有SPListCollection实现的“老派”集合,所以 C#/LINQ(无论如何在编译时)无法分辨它包含什么类型的项目。该调用有助于解决此问题 - 它将 a转换为,允许类型代数在 compile-time 解决。您的循环没有这个问题,因为您明确指定了循环变量的类型 - 编译器代表您为序列中的每个项目插入一个强制转换。IEnumerableIEnumerable<T>Cast<SPListItem>()IEnumerableIEnumerable<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);
于 2013-03-08T14:57:42.213 回答
2

Ani 有更好的解决方案 IMO,但您还缺少另一件事:您的 LINQ 语句正在创建匿名项目的集合,但您没有为该匿名类中的属性命名。

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

为此,您需要专门声明名称:

new { Key = i.Title, Value = i["Value"].ToString() }
于 2013-03-08T15:08:06.347 回答