Michel Keijzers
Michel Keijzers

Reputation: 15367

Is this 'pattern' ok or is there a better method?

I have several classes in my app (just a fragment):

public abstract class Element {...}

public abstract class Program : Element
{
    ...

    public void SpecificProgramCall();
}

When I know a variable patch is of subtype Program I use:

((Program) element).SpecificProgramCall();

or better:

var patch = patch as Program;
Debug.Assert(patch != null);
patch.SpecificProgramCall();

When I don't know if it is a program:

var patch = patch as (Program);
if (patch != null)
{
    patch.SpecificProgramCall();
}

However, my code is (will be) full of these constructs. Is there a better way to implement this?

Example:

var usedProgramBank = ((SetListSlot) setListSlot).UsedPatch.Parent as ProgramBank;
var key = new Tuple<ProgramBank, Program>(usedProgramBank, ((SetListSlot) setListSlot).UsedPatch as Program);
if (_dict.ContainsKey(key) && !_dict[key].Contains(setListSlot))
{
    _dict[key].Add(setListSlot);
}

Upvotes: 0

Views: 83

Answers (2)

Theodoros Chatzigiannakis
Theodoros Chatzigiannakis

Reputation: 29223

Without more specific information about these types (including their semantics, your access to their code, etc), I'd say that this pattern is generally a candidate for dynamic dispatch. For example:

public abstract class Element
{
    public virtual void MaybeSpecificCall()
    {
        // nothing in most cases
    }
}

public abstract class Program : Element
{
    public override void MaybeSpecificCall()
    {
        base.MaybeSpecificCall();

        // but in this specific case, do something
        SpecificProgramCall(); 
    }

    public void SpecificProgramCall() { /* ... */ }
}

Then you can just do patch.MaybeSpecificCall() at the call spots and let the dynamic dispatch mechanism decide between doing something and doing nothing.


Alternatively, if you don't want to mess with the base class and you're only interested in not seeing the 'ugly' type checks, then a helper method could do the trick:

static void IfProgram(this Element element, Action<Program> action)
{
    var program = element as Program;
    if(program != null) action.Invoke(program);
}

And, again, you call it using patch.IfProgram(x => x.SpecificProgramCall()). I personally like lambdas, but whether they're ugly for this job is up to you.

Upvotes: 1

HypnoToad
HypnoToad

Reputation: 605

It depends on what kind of behavior you want from your code. If you declare a SpecificProgramCall() method in class Element as virtual, then you can override it in derived classes. In the base class you can either throw an error or handle it gracefully. That could simplify code for calls to SpecificProgramCall.

For example, if SpecificProgramCall returns an object, then in the base class you could return null and in the derived class return an object. Then all you have to do is check if the result of SpecificProgramCall is null.

There has to be accountability somewhere in your code if you're using polymorphism. Where you want to put it is up to you and ultimately depends on the structure of the rest of the program.

Upvotes: 1

Related Questions