I've been trying to work around C# not having polymorphic dispatch based on the method argument type, and I have encountered that you can't pass types around.
I basically have an abstract class Model
that implements two methods: IEnumerable<Decision> GetDecisions()
and void TakeDecision(Decision decision)
. Decision
is an abstract class as well. The consumer of this class repeatedly gets possible decisions, evaluates them and passes the best one back to the Model
.
Each single derived model can work with some common decisions and some model-specific decisions and I have a separate TakeDecision()
method for each Decision
type this specific Model
can work with. The problem is of course with single dispatch. Ideally, the consumer would do this:
var m = ModelFactory.GetModel(some parameters); //m is type Model
var ds = m.GetDecisions(); //ds is IEnumerable<Decision>
//Some logic here to choose the best Decision d
m.TakeDecision(d);
Now I have to implement logic that looks like this in every derived Model
, because C# can dispatch to the correct Model
implementation, but not to the correct overload:
if (decision is FooDecision) TakeDecision((FooDecision)decision);
if (decision is BarDecision) TakeDecision((BarDecision)decision);
...
or I force the consumer to do the casting on their side (they have most likely already done it to examine the decision).
I wanted to have a list of System.Type
s in each derived class, so I could do this:
foreach (var t in AllowedDecisionTypes) {
if (decision is t) TakeDecision((t)decision);
}
but it looks like System.Type
is not a real type:
- You can't do this:
AllowedDecisionTypes.Add(FooDecision)
, but you can doAllowedDecisionTypes((new FooDecision()).GetType())
- And vice versa, you can't do
decision is AllowedDecisionTypes[0]
, but you can dodecision is FooDecision
.
Is there a way to have both? I.e., generate a list of types and cast to them? Or is the only way out to do double dispatch and implement void Decision.ApplyTo(Model model) { model.TakeDecision(this); }
, on each decision, which should probably dispatch to the correct overload, since this
is now a specific Decision
?
To add a
Type
to a list ofType
objects you simply need to use thetypeof
operator instead of just adding the type.The equivalent operation to
is
for aType
objects is to use itsIsAssignableFrom
method.You won't be able to cast an object based on a
Type
; the way to call one of multiple overloads based on aType
is through reflection.