【问题标题】:ForEach giving Invalid Cast at RuntimeForEach 在运行时给出无效的演员表
【发布时间】:2011-06-29 18:10:39
【问题描述】:

我有以下几点:

 foreach (ItemOption itemOption in p.Items.Select(e => e.ItemOption).GroupBy(e => e.Id))
  { // do some work on itemoptions }

这编译。 但是在运行时我得到一个 Invalid Cast 异常:

无法将“Grouping[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+Grouping[System.String, MyNamespace.ItemOption]


更新 根据答案,我整理了一个更简单的案例来证明这个问题

给定对象:

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,这无法由编译器确定。

【问题讨论】:

    标签: c# linq types foreach


    【解决方案1】:

    这是因为String类不能被继承,但是你的ItemOption类可以被继承,也可以隐式转换。

    【讨论】:

      【解决方案2】:

      ItemOption 可能不是密封类(与 System.String 不同),因此 p.Items.Select(...).GroupBy(...) 的结果可能是 IGrouping&lt;...&gt; 的实现,它们 也是 ItemOption 值。编译器不知道,所以它插入了一个隐式转换。由于string 没有实现IGrouping&lt;...&gt; 并且是密封的,因此编译器可以发现这绝对是一个错误。

      foreach总是在必要时包含演员表。有点讨厌,因为它被隐藏了……但如果没有它,foreach 使用预泛型会非常痛苦。

      现在至于为什么它实际上是错误的......结果中的每个项目都将是一个分组而不是单个项目。如果您在处理结果方面需要更多帮助,请告诉我。

      【讨论】:

      【解决方案3】:

      关于演员阵容失败的原因:

      foreach (ItemOption itemOption in p.Items.Select(e => e.ItemOption).GroupBy(e => e.Id))
      

      您的.GroupBy 不会返回由 id 分组的 ItemOptions 列表。相反,它返回一个列表列表:第一个列表包含所有单独的 Ids,并且对于每个 Id,都有一个具有相同 Id 的 ItemOptions 列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多