The question of downcasting has been raised on SO before, but I couldn't find any explanation on how to avoid it properly.
Consider this hierarchy, for example.
abstract class NetworkDevice
{
//some common fields & properties
}
class Router : NetworkDevice
{
//some router-specific fields & properties & methods
}
class Switch : NetworkDevice
{
//some switch-specific fields & properties & methods
}
At some points I want to treat routers and switches and the rest of networking devices similary, based on their common properties (hence the base class), but at some points - differently, considering their unique qualities.
The question is - how do I properly switch from one case to another?
Say, there's List<NetworkDevice>
, received from some source. Now, when user selects one NetworkDevice
from the list, I need to show all the specific information (switch/router/etc specific) and populate visual controls with values.
The way I understand, someone has to downcast NetworkDevice to a derived class to do that, but how would that someone go about it so that the incapsulation is preserved?
The only way to go about it that I can see at the moment is to modify NetworkDevice
like this:
abstract class NetworkDevice
{
Type type {get; set;}
//etc...
}
or to define Enum NetworkDeviceType { Router, Switch, ...}
for the same purpose.
Either way we end up with this kind of code:
void DifferenciateNetworkDevice (NetworkDevice device)
{
...
switch (device.type)
{
case Switch: //or NetworkDeviceType.Switch
ShowSwitchProperties(device as Switch);
break;
case Router: //or NetworkDeviceType.Router
ShowRouterProperties(device as Router);
break;
...
}
}
That leads to long switch
statements and doesn't seem very encapsulating.
So, what am I missing? What would be the right way to go about it?
P.S. Reflection, I hope, wouldn't be a common approach in this situation and could be avoided. P.P.S. English is my second language, so I'm sorry for the mistakes.