tags:

views:

192

answers:

4

I'm writing an implementation of a virtual machine in C#, and I need to implement the VM's stack, which can contain two types of entry - return entries or backtrack entries. What is the best way of implementing this?

I'm currently using a base type, as follows:

class StackEntry { }
class Return : StackEntry { uint pc; }
class Backtrack : StackEntry { uint pc; object backtrack; }

Stack<StackEntry> stack;

This works OK, but the resulting type testing and downcasting feels clumsy.

Is there a better way of handling this type of construction?

+2  A: 

Why should you need to down cast? If your base class exposes abstract or virtual members, or is instead an interface, you should have no problem. This principle is the foundation of OOP.

If that doesn't work for you then you do a switch on myStack[x].GetType()

Andrew Bullock
+3  A: 

What's wrong with putting the BackTrack object in anyway and have it be null if there is no back track? You can add a helpful property like bool IsBacktrack { get { return _backTrack != null; } }

Can the backtrack be validly null? If yes, then use a bool flag for it.

plinth
+5  A: 

I'm having a hard time imagining how you're going to use this, but the basic answer is that you use a single type with a default operation for post-pop processing

StackEntry { protected virtual void PostPop(); }
Return : StackEntry { protected override void PostPop(); }
Backtrack : StackEntry { protected override void PostPop(); }

Does that make sense?

Mike Burton
please explain or give a concrete example
Greg Ogle
I'm afraid I couldn't really give a concrete example without a further elaboration of scope for the backtrack member of the Backtrack class. The question for the OP is basically this: What does the backtrack member represent? Is it an execution context?
Mike Burton
A: 

It depends on the level of abstraction that you expect. The base class method is quite nice. Only when benchmarks reveal that too much performance is lost this way, I would try to drill deeper, perhaps using a custom-tailored structure with explicit memory layout that acts similar to a C union.

How does your code affect usability in a negative way?

Konrad Rudolph