在 IEnumerable 上使用 LINQ 时出现编译器错误<dynamic>,但如果先将其强制转换为 IEnumerable 则不会出错<dynamic>



OK,所以我正在编写一些非常混乱的代码,因为我正在使用的库正在返回动态类型层次结构。其中一些类型可以展开为动态类型列表,为了使我能够在LINQ中使用这些动态对象层次结构,我编写了一个小方法,基本上将一些动态对象转换为IEnumerable

我有这个方法返回一个IEnumerable但是当我尝试使用它与LINQ我得到的错误"不能使用lambda表达式作为参数动态调度的操作,而不首先将其转换为委托或表达式树类型",但是,如果我从IEnumerableIEnumerable(在我看来没有操作),它编译和工作得很好。

谁能给我解释一下这种行为?
void Main()
{
    Foo(null).Select(value => value); // OK... I was expecting this to work.
    dynamic unknown = new ExpandoObject();
    Foo(unknown).Select(value => value); //COMPILER ERROR: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type... this was a bit more unexpected.
    ((IEnumerable<dynamic>)Foo(unknown)).Select(value => value); // OK... this was really unexpected.
}
IEnumerable<dynamic> Foo(dynamic param)
{
    yield return "Tranformation logic from param to IEnumerable of param goes here.";
}

Foo(unknown)的结果是dynamic,而不是IEnumerable<dynamic>。这是因为对Foo的调用是动态解析的,因为unknowndynamic

要静态解析Foo,可以写object unknown = new ExpandoObject();,或者将调用改为Foo((object) unknown)

更糟糕的是dynamic不支持扩展方法。即使Tdynamic,也可以静态地找到IEnumerable<T>上的扩展方法,但是c#编译器不提供活动using名称空间的列表,所以如果您有普通的dynamic,则运行时不知道要搜索哪些类来搜索扩展方法。即使.Select(value => value)可以编译,也许通过将其转换为Func<dynamic, dynamic> projection = value => value;,然后再转换为unknown.Select(projection)(未经测试),它仍然会在运行时抛出异常。您需要显式地编写Enumerable.Select(unknown, projection)以使其工作

相关内容

  • 没有找到相关文章

最新更新