在IEnumerable上执行LINQ时抛出异常

时间:2013-05-01 14:11:30

标签: linq types casting ienumerable any

假设我有两个班级,

class A
{
}

class B : A
{
}

我有一个接受foo

类型参数IEnumerable<A>;的方法
void AMethod(IEnumerable<A> foo)
{
}

,而是传入IEnumerable<B>类型的值。

AMethod(new[] { new B() });

这会编译并执行,但执行foo时已隐式转换为IEnumerable<B>。现在让我们说我的IEnumerable<B>包含A类对象(我不相信它们是混合还是全部相同)。当我致电foo.Any()时,我得到一个例外:

  

无法将类型为'A'的对象强制转换为'B'

我理解我无法将基类转换为子类,但这不是我想要做的事情(实际上在执行的这一点上,我甚至不关心它是什么类型)。我猜LINQ本身就是在试图进行这种转换,可能是基于foo类型为IEnumerable<B>的事实。所以,似乎我需要编写两个单独的方法,一个处理IEnumerable<A>,另一个处理IEnumerable<B>。我不明白为什么我需要这样做。有什么想法吗?

编辑:

有一些动态的转换和转换正在设法吐出一个填充了'A'的IEnumerable<B>,直到现在我认为这也是不可能的。我将尽力翻译此方法调用之前发生的事情:

protected void SetDynamicData(dynamic data)
{
  _data = data;
  IsB = typeof(IBInterface).IsAssignableFrom(_data.DataType);
}

...

var foo = IsB ? _data.Cast<B>() : data.Cast<A>();
return BuildJqGridData<A, B, int>(gridModel, foo);

1 个答案:

答案 0 :(得分:0)

IEnumerable<B>不能包含A类型的对象,因为A不是B

我可以写这段代码,

IEnumerable<B> dodgy = (new[] { new A() }).Cast<B>();

它会编译,尽管显然是错误的。编译器假设我知道我在做什么。请记住,IEnumerable序列中的任何项目尚未进行评估。

当我编写评估dodgy成员的代码时,由于A不是B且不支持转换为B,我会收到异常。

我可以写

IEnumerable<A> fine = new[] { new B() };

不需要强制转换,一切正常,因为BA


如果我这样做,

var hungrilyDodgy = (new[] { new A() }).Cast<B>().ToList();

Tolist()将强制枚举和评估IEnumerable,因此会更快地抛出异常。