Best way to switch behavior based on type [duplicate]
Possible Duplicate:
C# - Is there a better alternative than this to ‘switch on type’?
Consider the classic:
class Widget { }
class RedWidget : Widget { }
class BlueWidget : Widget { }
For the most part, in my UI, I can treat all Widget
s the same. However, there are minor differences, which I need to if
or switch
through.
Possible approaches:
Enum Indicator - set by constructor
enum WidgetVariety { Red, Blue }
class Widget {
public WidgetVariety Variety { get; protected set; }
}
class RedWidget : Widget {
public RedWidget() {
Variety = Red;
}
}
// Likewise for BlueWidget...
switch (mywidget.Variety) {
case WidgetVariety.Red:
// Red specific GUI stuff
case WidgetVariety.Blue:
// Blue specific GUI stuff
}
Use is
Widget w = ...;
if (w is RedWidget) {
(RedWidget)w ...
}
else if (w is BlueWidget) {
(BlueWidget)w ...
}
The reason I've resorted to this is 1) Most of the code is already somewhat written this way, but much uglier. 2) 90% of the code is identical - basically just one column in a GridView needs to be handled differently depending on the type.
Which would you recommend? (Or anyone have a better solution?)
Edit I know I'll probably be recommended to the Visitor Pattern, but that simply seems to complicated for sparse, minor differences in this case.
Edit 2
So one particular difference I was having a hard time sorting out is this column that is different between the two types. In one case, it retrieves a bool
value, and assigns that to the grid cell. In the other case, it gets a string value.
I suppose in this case, it should be obvious that I could define:
public object virtual GetColumn4Data();
public override GetColumn4Data() { return m_boolval; }
public override GetColumn4Data() { return m_mystring; }
This felt wrong to me initially, due to the use of object
. However, that is the type of the property that I am assigning to in the cell, so of course this makes sense!
Too long at the office today it seems...
There's another possibility. Use virtual dispatch:
class Widget
{
public virtual void GuiStuff() { }
}
class RedWidget : Widget
{
public override void GuiStuff()
{
//... red-specific GUI stuff
base.GuiStuff();
}
}
class BlueWidget : Widget
{
public override void GuiStuff()
{
//... blue-specific GUI stuff
base.GuiStuff();
}
}
Subtype polymorphism is the best solution, avoiding this kind of checks is one of the main reasons OO was created.
Widget
might have a method DoSomething()
(abstract probably) and then RedWidget
and BlueWidget
would override it.
Also see Martin Fowler's Replace Conditional with Polymorphism:
Seen: You have a conditional that chooses different behavior depending on the type of an object.
Refactor: Move each leg of the conditional to an overriding method in a subclass. Make the original method abstract.