Himberjack
Himberjack

Reputation: 5792

How to cast C#'s linq WHERE statement?

I have a class Literal and a Tag is inheriting from it.

I would like to do the following but I am getting

Unable to cast object of type 'WhereListIterator`1[Core.Literal]' to type 'System.Collections.Generic.List`1[Core.Tag]'.

 private List<Literal> literals;
public List<Tag> Tags
        {
            get { return (List<Tag>)literals.Where(x => x is Tag); }
        }

thanks

Upvotes: 10

Views: 16073

Answers (7)

Joshua Rodgers
Joshua Rodgers

Reputation: 5404

You would be better off doing:

literals.OfType<Tag>().ToList();

This gives you a List<Tag>.

You can also do:

var asList = new List<Tag>(literals.OfType<Tag>());

Casting simply does not work because LINQ works in terms of either IEnumerable<T> or IQueryable<T> which neither use List as a backing implementation for the results. The second method I posted uses a constructor overload of List<T> the takes in an IEnumerable<T> as its initial collection of objects. Also in this scenario the OfType<T> method from LINQ is a much cleaner, shorter form of essentially filtering a list with Where(x -> x is T).

Also, OfType<T> in this scenario is a much better idea, because the result is an IEnumerable<T> of your target type. Where(x => x is T) will return an IEnumerable<T> of the original source's type. So that's why (List<Tag>)literals.Where(x => x is Tag).ToList() emit an error for invalid casts.

More information on ToList

More information on OfType

Upvotes: 36

Jean-Philippe Leclerc
Jean-Philippe Leclerc

Reputation: 6805

List<Tag>)literals.Where(x => x is Tag).ToList();

or even better :

literals.OfType<Tag>();

then you can create a new list from it:

new List<Tag>(literals.OfType<Tag>());

Upvotes: 1

Guffa
Guffa

Reputation: 700242

The Where method returns the same type as the source, so you would have to cast each item, then use the ToList method to create a list from the result:

return literals.Where(x => x is Tag).Select(x => (Tag)x).ToList();

You can also us the OfType method:

return literals.OfType<Tag>().ToList();

Upvotes: 0

Tony Kh
Tony Kh

Reputation: 1572

try the following:

literals.Where(x => x is Tag).Cast<Tag>().ToList();

it works if Tag is derived from Literal

Upvotes: 0

rrhartjr
rrhartjr

Reputation: 2114

How about adding ToList()?

Your getter becomes: literals.Where(x => x is Tag).ToList();

Upvotes: 0

Emond
Emond

Reputation: 50672

Depending on the effect you want you could do this:

public List<Tag> Tags
{
    get { return literals.Where(x => x is Tag).ToList(); }
}

Do realize that this is not a cast but the creation of a list!

Upvotes: 0

Luk&#225;š Novotn&#253;
Luk&#225;š Novotn&#253;

Reputation: 9052

literals.Select(x => x as Tag).Where(x => x != null).ToList()

Note that this will return new list. You won't be able to do where and modify original list by this. Also this can be done like this: literals.OfType<Tag>().ToList() and it will return IList<Tag>

Update: modified type

Upvotes: 7

Related Questions