我有一个名为Item的类,我在这个类上执行LINQ查询但是我注意到当我尝试使用group
运算符时:
我无法访问IEnumarable
等key
接口扩展方法。
类似的东西:
var groupByQuery =
from item in items
group item by item.ItemType[0];
foreach (Item item in groupByQuery)
{
Console.WriteLine(item.Key);
...
}
会产生错误:
`Error 1 'ProductCatalog.Item' does not contain a definition for 'Key' and no extension method 'Key' accepting a first argument of type 'ProductCatalog.Item' could be found (are you missing a using directive or an assembly reference?)`
我需要将其更改为:
foreach (var item in groupByQuery)
{
Console.WriteLine(item.Key);
...
}
让它发挥作用。我只需要理解为什么会发生这种情况。我头脑中的一些东西告诉我这与Item
的类型和Key
类型的返回有关,但这就是它。
答案 0 :(得分:2)
如果您只是使用item
行的IntelliSense和鼠标悬停item in groupByQuery
,您会看到这些类型的差异。
使用var item
将使用由表达式生成的类型,IGrouping<T, Item>
(我在此处写了T
,因为我不知道ItemType[0]
的类型)。
使用Item item
会将其转换为Item
,如您所料。如错误所述,类Item
未实现Key
。如果您选择这样做,您可以在班级中明确地执行此操作,但这可能不是最好的方法。原因是,通常当您使用group by
时,您将返回一组Item
,这与Item
的单个实例不同(假设将有多个Items
ItemType[0]
)。因此,您可能更喜欢使用实现ItemGroup
的新类(例如IGrouping<T, Item>
)或重新考虑查询。
答案 1 :(得分:0)
组查询返回IEnumerable组。一个组有一个Key和一个IEnumerable。所以,你的for循环可能是这样的:
foreach (var group in groupByQuery)
{
Console.WriteLine(group.Key);
foreach (var item in group)
{
Console.WriteLine(" {0}", item);
}
}
您的问题更多是关于foreach
。 foreach
似乎等同于从第一个元素到最后一个元素(或for
)的while
或break
索引。使用foreach (Item item in groupByQuery)
,它似乎从这样开始:
Item item = groupByQuery.ElementAt(0);
但是,由于组不是Item类型,因此无法编译。
关于foreach
的非直观但完全记录的事情是编译器将其翻译为就像它编码如下:
{
E e = ((C)(x)).GetEnumerator();
try {
while (e.MoveNext()) {
V v = (V)(T)e.Current;
embedded-statement
}
}
finally {
… // Dispose e
}
}
其中V是循环控制变量的给定或隐式类型。它执行强制转换,即使您更喜欢编译器错误,也可能在运行时失败。转换将是我们对非通用IEnumerable的意图。实际上,foreach
没有IEnumerable<T>
,foreach
的降级为IEnumerable
。
如果您想知道原因,请参阅Eric Lippert's blog。