c# - 如何在 GetEnumerator 中返回动态实体
问题描述
我的课程是从IEnumerable<T>
:
public class MyList<T> : IEnumerable<T>
{
IQueryable Queryable;
public MyList(IQueryable ts)
{
Queryable = ts;
}
public IEnumerator<T> GetEnumerator()
{
foreach (var item in Queryable)
{
yield return (T)item;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
当我从中选择一些属性时IQuerable
,ToList()
它可以工作:
IQueryable propertiesFromClasses = classesIQuerable.Select(a => a.Property);
MyList<MyClass> classes = new MyList<MyClass>(propertiesFromClasses);
var toListResult = classes.ToList();
现在,我想选择动态类型:
IQueryable propertiesFromClasses = classesIQuerable.Select(a => new { SelectedProperty = a.Property });
MyList<MyClass> classes = new MyList<MyClass>(propertiesFromClasses);
var toListResult = classes.ToList();
yield return (T)item;
它在方法中抛出异常GetEnumerator()
:
System.InvalidCastException:'无法将'<>f__AnonymousType0`1[System.String]'类型的对象转换为'MyClass'类型。'
解决方案
问题显然出在MyClass<T>
.
做一个合适的构造函数
首先,如果你想实现一个MyClass<Order>
代表一个可枚举对象序列的类Order
,为什么要允许一个接受的构造函数IQueryable<Student>
呢?
只接受一个序列Orders
或至少一个可以转换为的项目序列不是更好Orders
吗?
这样你的编译器就会抱怨,而不是稍后在代码执行期间。
public class MyList<T> : IEnumerable<T>
{
IQueryable<T> queryable;
public MyList(IQueryable<T> ts)
{
this.queryable = ts;
}
public IEnumerator<T> GetEnumerator()
{
return this.Queryable;
}
...
}
如果你这样做了,你的编译器就会抱怨,而不是运行时异常。
您在第二段代码中创建的对象是一个实现IQueryable<someAnonymousClass>
. 你的调试器会告诉你这个对象没有实现IQueryable<MyClass>
实现的对象IQueryable<someAnonymousClass>
也实现了IQueryable
. 但是,可以从 this 枚举的元素IQueryable
属于类型,如果没有适当的转换方法,someAnonymousClass
这些对象就无法转换为。MyClass
您的第一段代码不会导致此问题,因为您创建的对象实现了IQueryable<MyClass>
,因此枚举器将产生对象,这些对象可以毫无问题MyClass
地转换为对象。MyClass
但是再说一遍:如果您创建了一个适当的构造函数,您会在编译时而不是在运行时注意到问题。
替代解决方案
可能是您真的想设计一个可以保存Students
in 序列并尝试从中提取 all的类Orders
,或者是一个更现实的问题:放置一个序列Animals
并枚举 all Birds
。这样的类可以从任何序列中提取所有 Birds:
public class FilteredEnumerator<T> : IEnumerable<T>
{
public FilteredEnumerator(IQueryable queryable)
{
this.queryable = queryable;
}
private readonly IQueryable queryable;
private IEnumerator<T> GetEnumerator()
{
return this.queryable.OfType<T>();
}
}
虽然这会奏效。我不确定这是否会是一堂非常有意义的课。已经有一个 LINQ 函数可以满足您的需求:
var bird = myDbContext.Animals.OfType();
推荐阅读
- python-3.x - 编写递归函数列出parts.txt的所有路径
- apache-spark - PySpark 根据列键将 DataFrame 拆分为多个帧,并在每个帧上训练一个 ML lib 模型
- asp.net-mvc - 在下拉列表中选择默认值并传递 id MVC 下拉列表
- python - Python smbus 读取数据
- android - Android:onUpgrade 后第一次尝试执行 getWritableDatabase() 时出现 SQLite“数据库锁定”异常
- javascript - 检测 Javascript/ECMAScript 等待滥用?
- javascript - 如何通过 onClick 事件将参数从列表项传递给函数
- python - 打印函数值
- swift - 如果我的 lineLimit 在 SwiftUI 中未达到 2,如何让我的 Text 在其堆栈顶部对齐?
- string - AppleScript:将 40 段分成 4 段的 10 段