为什么 Select() 不将 IEnumerable转换为 IEnumerable到 IEnumerable?
我尝试使用 Dapper 将数据库表映射到 C# 中的类型,但是,我的某些类型需要表中没有的其他元素。为此,我使用一个可以获取列值并设置适当属性的工厂。
public IEnumerable<IMyType> All() {
var query = _connection.Query("SELECT * FROM [table]");
return query.Select(o => _myTypeFactory.Create(o));
}
目前,这导致 return 语句生成错误:
无法将表达式类型 'System.Collections.Generic.IEnumerable
转换为返回类型 'System.Collections.Generic。 IEnumerable
我的工厂类看起来像这样:
public class MyTypeFactory {
public IMyType Create(dynamic o) {
return Create((String) o.Code, (Int32) o.KeyID);
}
public IMyType Create(String code, Int32 keyID) {
return new MyType(code, Cache.Lookup(keyID));
}
}
为什么 Select()
方法不返回IEnumerable
?我需要做什么才能使这项工作成功?这是错误的方法吗?还有更好的方法吗?
I'm trying to use Dapper simply to map my database tables to types in C#, however, some of my types need additional elements that are not in the table. To do this I am using a factory that can take column values and set the appropriate properties.
public IEnumerable<IMyType> All() {
var query = _connection.Query("SELECT * FROM [table]");
return query.Select(o => _myTypeFactory.Create(o));
}
Currently this is resulting the return statement generating an error:
Cannot convert expression type 'System.Collections.Generic.IEnumerable<dynamic>'
to return type 'System.Collections.Generic.IEnumerable<IMyType>'
My factory class looks something like this:
public class MyTypeFactory {
public IMyType Create(dynamic o) {
return Create((String) o.Code, (Int32) o.KeyID);
}
public IMyType Create(String code, Int32 keyID) {
return new MyType(code, Cache.Lookup(keyID));
}
}
Why doesn't the Select()
method return IEnumerable<IMyType>
? What do I need to do to make this work? Is this just the wrong approach and there's a better way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
最简单的修复方法就是使用
Cast<>
LINQ 运算符:或者,您可以强制转换每个元素:
它当前不起作用,因为
IEnumerable之间根本没有可用的隐式转换;
和IEnumerable
。IEnumerable
可以通过多种方式实现,并且鉴于每个项目都将动态生成,因此没有理由假设结果值将实现IEnumerable< ;IMyType>
。我同意它看起来就像第二种形式实际上没有添加任何东西,但是编译器不会检查
_myTypeFactory.Create( 的所有可能返回类型o)
- 它将整个表达式视为动态值,即表达式的类型为dynamic
。因此,Select
结果仍然是IEnumerable
类型。另一种选择是为
Select
指定泛型类型参数。这是试图将 lambda 表达式强制为
Func
- 我相信会起作用...编辑:如注释中所述,强制方法调用在编译时解决也会修复它。基本上这取决于您认为最可读的内容。
The simplest fix is just to use the
Cast<>
LINQ operator:Alternatively, you could cast each element:
It doesn't currently work because there's simply no implicit conversion available between
IEnumerable<dynamic>
andIEnumerable<IMyType>
.IEnumerable<dynamic>
could be implemented in any number of ways, and given that each item will be generated dynamically there's no reason to suppose the result value will implementIEnumerable<IMyType>
.I agree that it looks like the second form isn't actually adding anything, but the compiler doesn't check all the possible return types of
_myTypeFactory.Create(o)
- it treats that whole expression as a dynamic value, i.e. the expression is of typedynamic
. Therefore theSelect
result is still of typeIEnumerable<dynamic>
.Another option is to specify the generic type argument to
Select
.That's attempting to force the lambda expression to a
Func<dynamic, IMyType>
- I believe that will work...EDIT: As noted in comments, forcing the method invocation to be resolved at compile-time will fix it too. Basically it depends what you find most readable.
最好的解决方法可能是从 select 语句中删除动态调用,然后您将获得预期的静态类型
IEnumerable
。或
The best fix is probably to remove the dynamic invocation from the select statement then you'll get your expected static type
IEnumerable<IMyType>
.OR