У меня есть следующее:
foreach (ItemOption itemOption in p.Items.Select(e => e.ItemOption).GroupBy(e => e.Id))
{ // do some work on itemoptions }
Это компилируется.
Однако во время выполнения я получаю исключение Invalid Cast:
Невозможно привести объект типа «Группировка [System.String, MyNameSpace.ItemOption]» к типу «MyNameSpace.ItemOption».
Если я изменю код, например, на Строка как тип элемента:
foreach (String itemOption in p.Items.Select(e => e.ItemOption).GroupBy(e => e.Id))
{ // do some work on itemoptions }
Тогда компилятор сообщает мне, что типы несовместимы.
Почему компилятор не помечает несовместимость типов в первом блоке кода?
Я провел дополнительное расследование и обнаружил, что, учитывая следующий код:
var foo = p.Items.Select(e => e.ItemOption).GroupBy(e => e.Id));
Type singleElementType = foo.ElementAt(0).GetType();
singleElementType
:
System.Linq.Lookup`2 + Группировка [System.String, MyNamespace.ItemOption]
UPDATE
Исходя из ответов, я собрал более простой пример, чтобы продемонстрировать проблему
Учитывая объекты:
interface IMyObj
{
string Id;
}
class MyObj : IMyObj
{
public string Id;
public MyObj2 cg;
}
class MyObj2
{
}
Это не удастся во время компиляции
IEnumerable<MyObj> compileTimeFailList = new List<MyObj>()
foreach (MyObj2 myObj2 in compileTimeFailList.Where(x => x.Id != null))
{
и произойдет сбой во время выполнения
IEnumerable<IMyObj> runtimeFailList = new List<IMyObj>();
foreach (MyObj2 myObj2 in runtimeFailList.Where(x => x.Id != null))
{
Причина в том, что объекты в runtimeFailList
могут расширять MyObj2, и компилятор не может определить это.