type casting with GetType

  • Thread starter Thread starter Dennis Myrén
  • Start date Start date
D

Dennis Myrén

If you know all the dervied objects and they are not too many,
i suggest the easiest way which is checking what type it is.

if (node is Num)
{
((Num) node).Something();
}
else if (node is AnotherDerived)
{
((AnotherDerived) node).SomethingElse();
}

or if some of the derivors share the same functions you could have another
base class on top
of Node.
if (node is ExtensionNode)
{
((ExtensionNode) node).Something();
}
or have them implement an interface or something.

If this is not an option for you, the only way is to use reflection to
dynamically call members,
but then you would need to know the name of the member to call anyway.
 
You can't dynamically cast at run time.

and even if you could in an imaginary world, it would still do you no good.
one, at compile time, it'd have no idea what your type is suppose to be, and
hence you can't call any methods. two, since your nodes are different, you'd
still need a different block to handle each individual case, and therefore
you are back to where you started.
 
I believe that an implementation of a vistor pattern may be the answer you
are looking for, check out:

http://www.dofactory.com/Patterns/PatternVisitor.aspx#_self1

It will allow you to remove messy if else ladders from your code


--
HTH

Ollie Riches
http://www.phoneanalyser.net

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a programmer
helping programmers.
 
Hi,

I dont think that you have other options but using a switch or several if

whta is what you want after all? maybe we can propose a better solution

cheers,
 
You may want to implement some type of tokenizing pattern and loop through
the expression and parse it.
 
Why did you design a OO system if you want to fight OO design?

What you want is lots of overloads of Evaluate(). Then, instead of
something whacky like:

if (node is Num)
{
((Num) node).Something();
}
else if (node is AnotherDerived)
{
((AnotherDerived) node).SomethingElse();
}

You merely have:

Evaluate(Num n1)
{ n1.Something(); }

Evaluate(AnotherDerived ad)
{ ad.SomethingElse(); }

Actually, what you REALLY want is to define Num & AnotherDerived so that
they both have a Something() method.
 
Perhaps you're one step away from a better design.

What you seem to be thinking now is, "I have many types of operands,
and one evaluator class. How do I make my evaluator class capable of
processing any kind of operand without making it grossly
overcomplicated, and having to change it for every new kind of operand
that I introduce?" Perhaps that's the wrong question.

What if you thought of it this way: "I have many types of operands, all
of which implement some basic methods and properties (so they all
derive from Node). I have many types of evaluators, all of which
implement some basic methods and poperties (so they all derive from
Evaluator)." Now your problem is to get the correct kind of Evaluator
for the kind of Node that you're trying to process.

I'm sure that if you look through Design Patterns you'll find some to
cope with this situation. I think you'll at least need some kind of
Factory: give it the Node you want to work with and it returns the
appropriate Evaluator to operate on that type of Node.
 
David Sobey said:
Maybe I should state my whole problem and see if anyone has any ideas. I'm
writing an equation parser, and Node is a parent class of Branch (which
links to other nodes with an operation), Num, and eventually Matrix,
complex, vector etc.

If I evaluate a Branch, say an addition Branch linked to a Num of 2 and a
Num of 3, before I can call the overloaded operator of +, i need to
specify that child nodes of branch are both Nums. This is where my casting
probs are. Eventually a branch can be linked to a multitude of types, and
this will cause hugely messy buggy code.

I presume you are passing 3 params into your functions, 2 nodes and an
operator represented somehow? Wouldn't it be best that the objects inherited
from node should know what to do, so your code would simply be

Node1.Evaluate Node2, OperatorType

Then have the bulk of the code in Node1 and Node2? This would mean the code
could be a simple switch statement.

Michael
 
hi

- I have a class Node, with a child class Num, that inherits from Node.
- I have a function "Evaluate" that takes two Nodes as an argument.
- I call this function by sending it two "Num"'s. When i use
GetType().ToSTring(), it seems to be aware that the arguments it recieved
are in fact Nums, not Nodes.

- How do I cast the arguments to Nums so I can use all the member functions
and variables, without doing
it manually, ie (Num)someVariable. I want to do this so I can send Evaluate
lots of different childs of Node, without having complicate
my code further for each addition. I can't figure out how to do it with
GetType().

Help most appreciated.
Cheers
dave
 
hmmm looks like this will be a hard one. The problem is, Num will soon be
joined joined by Matrix, Vector, Complex, etc. And in groups of 2, that'll
make a lot of If statements!
 
Maybe I should state my whole problem and see if anyone has any ideas. I'm
writing an equation parser, and Node is a parent class of Branch (which
links to other nodes with an operation), Num, and eventually Matrix,
complex, vector etc.

If I evaluate a Branch, say an addition Branch linked to a Num of 2 and a
Num of 3, before I can call the overloaded operator of +, i need to specify
that child nodes of branch are both Nums. This is where my casting probs
are. Eventually a branch can be linked to a multitude of types, and this
will cause hugely messy buggy code.

Any ideas appreciated.

Cheers
dave
 
You see I can't do that because here's the def for Branch:Node:

class Branch:Node
{
public Node left;
public Node right;
public Operations operation;
public Node Evaluate(arguments here)
etc......

When i assign child nodes to a branch, for ex:

Num num=new Num();
num.val=10;
myBranch.left=num;
myBranch.right=OtherNum;

It does not then consider myBranch.left to be of type Num, just because
I assigned Num's to them. So i can't overload Evaluate because I'll only
ever have two Node's as my arguments.

Cheers and thanks
dave
 
OK here goes **Holds breath**:

enum Operations {Add, Subtract};

class Class1
{
public class Node
{
}

class Branch:Node
{
public Node left;
public Node right;
public Operations operation;
static num evaluate (num l, num r)
{
num result=new num();
if (this.operation==operations.add)
{
result.val=l.val+r.val;
return result;
}
else
{
result.val=l.val-r.val;
return result;
}
}
}

internal class Num:Node
{
internal int val;

public static Node operator +(Num l, Num r)
{
Num result=new Num(l.val+r.val);
return result;
}
}

static void Main(string[] args)
{
Num l=new Num();
l.val=5;

Num r=new Num(6);
r.val=6;

Branch top=new Branch();
top.Type=Types.Branch;
top.left=(Num)l;
top.right=(Num)r;
top.operation=Operations.Add;

Node n=new Node();
Node dog=new Num();

n=Branch.Evaluate(top.l, top.r);
}
}
}

Num will eventually be joined by matrix, vector, complex, etc.

It spit out an error when i call evaluate, because despite top.l and
top.r pointing to nums, they are actually node types.

cheers
dave
 
First of all static methods such as operators (+, -) cannot be used as virtual methods and so it is hard to achieve dynamic binding.
I agree with Michael. You can create a virtual method in the base node class called Evaluate and override it in Num, Matrix etc. And Branch's evaluate simply treats left and right as nodes and calls node.Evaluate which will be bound to Num/Matrix at runtime automatically.

I have made some additional comments in your code. And I think looking at the pdf I sent earlier and remodelling your classes will help.
 
David Sobey said:
You see I can't do that because here's the def for Branch:Node:
So i can't overload Evaluate because I'll only
ever have two Node's as my arguments.

Sure you can.... You just need to be a bit more creative....

Node Node::Evaluate(Node n1, Node n2)
{ return n1.Evaluate(n2); } // polymorphically calls
Num::Evaluate(Node);

virtual Node Num:Evaluate(Node n2)
{ return n2.Evaluate(*this); } // polymorphically calls
Num::Evaluate(Num);

virtual Num Num:Evaluate(Num n1)
{
// Do Real Work here.....
return Node::EvaluateNumNum(n1, *this);
}

To expand it, say we have 3 different options:

EvaluateNumNum(Num lhs, Num rhs);
EvaluateNumMatrix(Num lhs, Matrix rhs); // Also used for Matrix & Num
EvaluateMatrixMatrix(Matrix lhs, Matrix rhs);

Then we would just need to add:

virtual Node Matrix::Evaluate(Node rhs)
{ return rhs.Evaluate(*this); } // calls either
Matrix::Evaluate(Matrix) or Num::Evaluate(Matrix)

virtual Matrix Num::Evaluate(Matrix lhs)
{ return EvaluateNumMatrix(lhs, *this); }

virtual Matrix Matrix::Evaluate(Matrix lhs)
{ return EvaluateMatrixMatrix(lhs, *this); }

virtual Matrix Matrix::Evaluate(Num lhs)
{ return EvaluateNumMatrix(*this, lhs): }


A fuller description of this technique is Item #31 in Scott Meyers's
book, "More Effective C++"
 
Back
Top