I am surprised that nobody mentioned multiple dispatch. The usual way to work around this is via Visitor pattern and that is not always possible so you end up with stacked is
checks.
So here is a real life example of an application of my own. Instead of doing:
public static MapDtoBase CreateDto(ChartItem item)
{
if (item is ElevationPoint) return CreateDtoImpl((ElevationPoint)item);
if (item is MapPoint) return CreateDtoImpl((MapPoint)item);
if (item is MapPolyline) return CreateDtoImpl((MapPolyline)item);
//other subtypes follow
throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}
You do:
public static MapDtoBase CreateDto(ChartItem item)
{
return CreateDtoImpl(item as dynamic);
}
private static MapDtoBase CreateDtoImpl(ChartItem item)
{
throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}
private static MapDtoBase CreateDtoImpl(MapPoint item)
{
return new MapPointDto(item);
}
private static MapDtoBase CreateDtoImpl(ElevationPoint item)
{
return new ElevationDto(item);
}
Note that in first case ElevationPoint
is subclass of MapPoint
and if it's not placed before MapPoint
it will never be reached. This is not the case with dynamic, as the closest matching method will be called.
As you might guess from the code, that feature came handy while I was performing translation from ChartItem objects to their serializable versions. I didn't want to pollute my code with visitors and I didn't want also to pollute my ChartItem
objects with useless serialization specific attributes.