Recently I came across the question how to build a special kind of polymorphic query, that returns only one specific member type out of many different types in a given source.
Lets assume these example class definitions (all examples given in Delphi Prism syntax – the idea applies to other .NET languages as well of course)
type Car = abstract class (Object) public HorsePowers: Integer; Model: String; Owner: String; end; Volkswagen = class(Car) public end; Porsche = class(Car) public SpeedLimiterActive:Boolean; end;
So we have an abstract Car class and two descendants: Volkswagen and Porsche. The VW class does not introduce any new behaviors, Porsche though introduces a SpeedLimiterActive fields of type Boolean.
Porsche has models which can go faster than 300km/h, but these may be artificially limited at lets say 250 km/h (which is still damn fast) To get the real full speed they have to disable a “SpeedLimiter” – to have them do that, the owner has to join a driver training – which is not for free of course
Now lets assume we are a car dealer who sells Volkswagen and Porsche. We want to go through our list of sold cars and find all Porsche owners that still have the SpeedLimiter enabled, so that we can invite these guys for that driver training:
First let’s create a list of cars:
var CarsSold := new List<Car>; CarsSold.add(new Volkswagen(Owner := 'Hadi', Model := 'Beetle', HorsePowers := 90)); CarsSold.add(new Porsche(Owner := 'Holger', Model := '911', HorsePowers := 310, SpeedLimiterActive := false)); CarsSold.add(new Porsche(Owner := 'Olaf' , Model := '911 turbo', HorsePowers := 480, SpeedLimiterActive := true));
Now how to go through that list via Linq so that we get Porsche owners only?
Below is the first attempt which basically works. The “ToList” at the end is just there to force Linq to actually go through the whole list.
var OwnersForDriverTraining := from c in CarsSold where c is Porsche select c.owner; OwnersForDriverTraining.ToList;
The problem is now that we wanted to select only those owners whose cars still have the SpeedLimiter enabled. So we would need something like “where c.SpeedLimiterActive = true”. Unfortunately that won’t work as not all items in the car list are Porsches that do have this field.
Putting in a “where c is Porsche” does not help either, if you give c an explicit type (Porsche):
// NON WORKING! var OwnersForDriverTraining := from c:Porsche in CarsSold where c is Porsche where c.SpeedLimiterActive = true select c.owner; OwnersForDriverTraining.ToList;
The problem is that this “where c is Porsche” is too late. Linq already tried to cast a Volkswagen as Porsche in the “from c:Porsche” expression. You could of course leave out the explicit c:Porsche, and could cast all cars as Porsche when you need them. In this simple example that would certainly work:
var OwnersForDriverTraining := from c in CarsSold where c is Porsche where Porsche(c) .SpeedLimiterActive = true select c.owner; OwnersForDriverTraining.ToList;
But wouldn’t it be more elegant to have Linq return Porsche items directly? What if you don’t have just one, but dozens fields/properties in your Linq query that would need the actual item to be type casted over and over again?
The trick is to use a lambda expression:
var OwnersForDriverTraining := from c: Porsche in CarsSold.Where(x -> x is Porsche) where c.SpeedLimiterActive = true select c.owner; OwnersForDriverTraining.ToList;
Here, the Lambda “where” is executed before the implicit c:Porsche type cast takes place.
Generally I prefer Linq query syntax over Lambda syntax, because in my opinion Linq query syntax is much better readable, thus better maintainable. In certain cases though it obviously makes sense to drop in a little Lambda to get clean code.





Entries (RSS)
Here elaborates the matter not only extensively but also detailly .I support the
write's unique point.It is useful and new balance a20 Navajo benefit to your daily life.You can go those
sits to know more relate things.They are strongly recommended by friends.Personally