How to use list.where function with the objects getting casted before getting an IEnumerable

Multi tool use
How to use list.where function with the objects getting casted before getting an IEnumerable
My classes are like this
public interface ICar
{
CarModel GetCarModel();
}
public class Honda: ICar
{
CarModel GetCarModel()
{
return CarModel.Honda;
}
}
I have a list of ICars
defined like this:
ICars
List<ICar> cars;
I am looking to extract a IEnumerable of all cars of type Honda using the Where clause and casted to Honda and not to ICar.
How do I do this? Is this possible?
public CarModel CarModel => CarModel.Honda;
public
Not, that type design like this leads to "double-typing". Noting prevents you from having
class MercedesBenz : ICar { CarModel GetCarModel() => CarModel.Honda }
. I'd recommend you to avoid it. The easiest you can do here is to throw away enumeration and use CLR type itself (@RichardSchneider's answer is the excellent example).– Dennis
Jul 1 at 11:02
class MercedesBenz : ICar { CarModel GetCarModel() => CarModel.Honda }
Why focus on using the
Where
method as it might exclude better code answers if strictly interpreted.. Just wondering..– Peter Bons
Jul 1 at 11:49
Where
Dennis, yes you are right. I could get rid of it, but may as well keep it to make logging easier if I change the enum to a property.
– sgowd
Jul 1 at 12:05
3 Answers
3
var result = cars.OfType<Honda>();
See the docs
This is definitely the simplest option.
– john
Jul 1 at 10:46
while your code is good, this is not really an answer, just a code dump. It should contain an explanation as well.
– Zohar Peled
Jul 1 at 10:46
In terms of performance, since there is the enum
CarModel
, I am not sure this solution would be the best choice.– Svek
Jul 1 at 10:48
CarModel
@Svek To quote performance you must show some numbers,
– Richard Schneider
Jul 1 at 10:53
@Svek in terms of performance, the
OfType
only needs to iterate the IEnumerable
once, while using Where
and then Select
needs one iteration over the entire IEnumerable
, and another one over the results of the Select
. so OfType
is a winner here. However, this solution relies on the assumption that each car type has it's own class (which seems correct based on the sample code) but it's still an assumption, and it might be the best fit in this particular case but generally speaking, the where...select
combination is a good fit for a broader range of selections.– Zohar Peled
Jul 1 at 10:53
OfType
IEnumerable
Where
Select
IEnumerable
Select
OfType
where...select
Where
only returns a filtered IEnumerable
. You need to use Select
also:
Where
IEnumerable
Select
var listOfHonda = cars.Where(c => c.GetCarModel() == CarModel.Honda).Select(c => (Honda)c);
There's also the Cast method,
.Cast<Honda>()
would be equivalent to .Select(c => (Honda)c)
– Patrick McDonald
Jul 1 at 10:59
.Cast<Honda>()
.Select(c => (Honda)c)
@PatrickMcDonald True, I forgot about that. thanks!
– Zohar Peled
Jul 1 at 11:01
You can do it, by something like this:
IEnumerable<ICar> results = cars.Where(s => s.GetCarModel == CarModel.Honda);
var hondas = results.Select(c => (Honda)c);
unless
Honda
can be implicitly converted to a string, this will not compile.– Zohar Peled
Jul 1 at 10:44
Honda
@ZoharPeled
Honda
is a class name in the context. Why in the world it should be converted to a string???– ananda
Jul 1 at 10:47
Honda
because the type of
results
you wrote is IEnumerable<string>
...– Zohar Peled
Jul 1 at 10:49
results
IEnumerable<string>
@ananda the fix is not really that great - now you are back to an
IEnumerable<ICar>
instead of an IEnumerable<Honda>
as stated in the question...– Zohar Peled
Jul 1 at 10:54
IEnumerable<ICar>
IEnumerable<Honda>
Sorry, I'm missed the separation to two lines
– Zohar Peled
Jul 1 at 11:02
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
BTW more idiomatic C# would use a property not a method:
public CarModel CarModel => CarModel.Honda;
and it would need to bepublic
to satisfy the interface.– Ian Mercer
Jul 1 at 10:53