C#: Chained Linq methods and casting
I have a little game, where I implemented some collision detection. Now I want to get a list of all items of a specific type, which are colliding with the current "Entity" object. I want to do something like this:
public List<T> GetCollidingObjects<T>() where T : Entity
{
return this.Game.World.Entities
.AsParallel()
.Where(e => e.IsColliding(this))
.Where(e => e is T)
.ToList<T>();
}
I get the following error:
Instance argument: cannot convert from "System.Linq.ParallelQuery<GameName.开发者_JAVA百科GameObjects.Entity>" to "System.Collections.Generic.IEnumerable<T>"
Can anyone explain, why this happens?
Thank you!
You cannot use ToList()
like that. The generic parameter you supply (if you choose to do so) must match the type of the sequence. It's a sequence of Entity
, not T
.
Anyway, you should use OfType()
to do the filtering, that's what it's there for.
public List<T> GetCollidingObjects<T>() where T : Entity
{
return this.Game.World.Entities
.OfType<T>()
.AsParallel()
.Where(e => e.IsColliding(this))
.ToList();
}
Jeff Mercado's answer is correct, but can be stated more plainly.
.Where(e => e is T)
This call to Enumerable.Where<Entity>
returns an IEnumerable<Entity>
(a filtered version of the source, which is an IEnumerable<Entity>
). The call does not return an IEnumerable<T>
.
Enumerable.Select<TSource, TResult>
and Enumerable.OfType<TResult>
can return an IEnumerable with a type different than the source:
.Where(e => e is T)
.Select(e => e as T)
or
.Select(e => e as T)
.Where(e => e != null)
or
.OfType<T>()
精彩评论