471,354 Members | 1,785 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,354 software developers and data experts.

Down casting objects

Tem
I have classes A,B,C,D,E,F that implement InterfaceBase.

Whats the best way to down cast obj to the correct type?

Is there a more elegant way to do this than?

Public Void DoSomething(InterfaceBase obj)
{
if(obj is A)
((A)obj).MethodThatOnlyACanDo();
else if(obj is B)
((B)obj).MethodThatOnlyBCanDo();
....
}

if and else if can become confusing when more options (more parameters,
child types) are added.

Tem

Jun 27 '08 #1
17 1239
I don't know that every method has to have a different name but if you
created a singular method in the base class and would override it in
the child classes with the same name you wouldn't have that problem.

I've run into a similar situation but it was because I needed to save
the objects differently so I had to know which one I was dealing with.

Jun 27 '08 #2
On Mon, 14 Apr 2008 13:49:51 -0700, Tem <te*****@yahoo.comwrote:
I have classes A,B,C,D,E,F that implement InterfaceBase.

Whats the best way to down cast obj to the correct type?

Is there a more elegant way to do this than?
I would agree with the reply from "cfps.Christian" that it would be much
better if you could simply declare a common abstract or virtual method in
the base class that each derived class could override.

If you really want to do what you're doing, casting it (or using the "as"
operator) is the only way to get to the derived type. However, if you
find yourself doing this, there's a very good chance that whatever
functionality you're trying to implement in your "DoSomething()" method
isn't being done in the best way anyway.

It's not that it never comes up. Just that it probably doesn't come up
nearly as often as one might think. If you have a method that "does
something" and takes some base class that can be inherited by different
sub-classes, and you expect each sub-class to "do" that "something"
differently, then the best way to represent that is with a single
overridden abstract or virtual method in the base class.

Pete
Jun 27 '08 #3
Tem... In addition to these suggestions, you could define an interface
IDoSomeThing and avoid the switch:

public void DoSomeThingIfPossible(InterfaceBase obj) {
if (obj is IDoSomething) {
( (IDoSomeThing)obj).DoSomething();
}
}

Regards,
Jeff

*** Sent via Developersdex http://www.developersdex.com ***
Jun 27 '08 #4
Tem
How would i do that if i have more than 1 parameter?

Public Void DoSomething(InterfaceBase obj1,InterfaceBase obj2)
{
if(obj1 is A && obj2 is A)
Method1(((A)obj1),((A)obj2);
else if(obj1 is A && obj2 is B)
Method2(((A)obj1),((B)obj2);
else if(obj1 is A && obj2 is C)
Method2(((A)obj1),((C)obj2);...

}
I have 36 possibilities, if and else if becomes very messy and lots of room
for making errors.
Im not sure how to use the method you mentioned with more than 1 parameter.
"cfps.Christian" <ge*******@otc.eduwrote in message
news:38**********************************@a22g2000 hsc.googlegroups.com...
>I don't know that every method has to have a different name but if you
created a singular method in the base class and would override it in
the child classes with the same name you wouldn't have that problem.

I've run into a similar situation but it was because I needed to save
the objects differently so I had to know which one I was dealing with.
Jun 27 '08 #5
On Tue, 15 Apr 2008 19:00:45 -0700, Tem <te*****@yahoo.comwrote:
[...]
I have 36 possibilities, if and else if becomes very messy and lots of
room for making errors.
Im not sure how to use the method you mentioned with more than 1
parameter.
It would really help if you could explain what it is exactly you're
doing. Do you literally have 36 different methods that will be called?

It's possible that the problem can be factored down to something that's
simpler. But if all we know about the problem is that you have 36
different possible outcomes, dependent on two different variables, it's
difficult to see how you'd make it simpler than a straight enumeration of
the possibilities.

If we knew more about the problem, it's likely that there's some
characteristic of it that would allow a simpler way to implement it. But
without that information from you, we're stuck.

Pete
Jun 27 '08 #6
Tem
I thought that would make the problem easier to understand...

It's a chemistry problem
elements
Li, Na, K, Rb, Cs, Fr
all implement interface IAlkaliMetal.

Public Void PrepareCombine(IAlkaliMetal elem1, IAlkaliMetal elem2)
{
if(elem1is Li && elem2 is Li)
Combine(((Li)elem1),((Na)elem2);
else if(elem1is Li && elem2 is Na)
Combine(((Li)elem1),((Na)elem2);
else if(elem1is Li && elem2 is K)
Combine(((Li)elem1),((K)elem2);...
}

This is to illustrate what im trying to do, they don't really combine this
way.
Combine method for each possible input types.
Public Void Combine(Li elem1, Li elem2){....}
Public Void Combine(Li elem1, Na elem2){....}
Public Void Combine(Li elem1, K elem2){....}

so again my question is there a way to design this so i so have to use all
those if else if statement and go directly to the corresponding Combine
method
If there are three inputs then there would be 216.

Ideally, it would just know which overload method to go to.
Public Void PrepareCombine(IAlkaliMetal elem1, IAlkaliMetal elem2)
{
Combine(elem1,elem2);
}

Is there a better way to design this?

Tem
"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
On Tue, 15 Apr 2008 19:00:45 -0700, Tem <te*****@yahoo.comwrote:
>[...]
I have 36 possibilities, if and else if becomes very messy and lots of
room for making errors.
Im not sure how to use the method you mentioned with more than 1
parameter.

It would really help if you could explain what it is exactly you're
doing. Do you literally have 36 different methods that will be called?

It's possible that the problem can be factored down to something that's
simpler. But if all we know about the problem is that you have 36
different possible outcomes, dependent on two different variables, it's
difficult to see how you'd make it simpler than a straight enumeration of
the possibilities.

If we knew more about the problem, it's likely that there's some
characteristic of it that would allow a simpler way to implement it. But
without that information from you, we're stuck.

Pete
Jun 27 '08 #7
On Wed, 16 Apr 2008 01:29:11 -0700, Tem <te*****@yahoo.comwrote:
I thought that would make the problem easier to understand...

It's a chemistry problem
elements
Li, Na, K, Rb, Cs, Fr
all implement interface IAlkaliMetal.
I don't understand this example:
Public Void PrepareCombine(IAlkaliMetal elem1, IAlkaliMetal elem2)
{
if(elem1is Li && elem2 is Li)
Combine(((Li)elem1),((Na)elem2);
If elem2 is Li, why are you casting to Na?

It's well and good to simplify your code examples, but you still need to
make sure that they are correct and compilable. I will assume that you
simply meant to write Li instead of Na here, and that you didn't intend to
leave off the required paren at the end of each method call in your
example.

That said, you still haven't really explained what these methods do. If
each possible combination really represents some different operation, then
I don't see any way out of at some point having to channel the flow of
execution down to one of those possible operations. If the operations are
specific to the combinations of the elements, then you will at some point
need some kind of comparison to resolve the combinations into individual
operations.

It's possible that you could represent these combinations in a table, with
delegates representing each method that handles the combination. Then
rather than having a bunch of if/else if statements, you could search the
table for the combination in question.

As far as extending this to combinations of three, again...what does this
operation do? With 216 combinations, do you really have 216 different
methods you might call?

Frankly, you haven't really clarified the problem. Your new example is
really pretty much the same as your original, except with different
names. It doesn't address the kinds of clarifications I was asking for.

Pete
Jun 27 '08 #8
Off the top of my pointed head. Each AlkaliMetal _could_ implement
IAlkiliMetal.Combine as an instance method
someAlkaliMetal.Combine(someAlkiliMetal). So a particular metal would
presumably know how to combine with any other metal including itself.

The static method CombineAlkiliMetals(someAlkiliMetal,someAlkiliMeta l)
could
simply checks for null parameters and then calls the appropriate
instance
method someAlkiliMetal.Combine. I can see a downside in duplication of
code
for am1.Combine(am2) and am2.Combine(am1), which, presumably, would have
the same implementation.

Regards,
Jeff

*** Sent via Developersdex http://www.developersdex.com ***
Jun 27 '08 #9
On Wed, 16 Apr 2008 19:34:25 -0700, Jeff Louie <an*******@devdex.com>
wrote:
Off the top of my pointed head. Each AlkaliMetal _could_ implement
IAlkiliMetal.Combine as an instance method
someAlkaliMetal.Combine(someAlkiliMetal). So a particular metal would
presumably know how to combine with any other metal including itself.
But would still have to check the type of the passed in object. Making it
an instance method might help with respect to breaking the problem down
into smaller, easier-to-manage parts. But it wouldn't reduce the total
number of type checks.

There's also a potential issue with respect to the three-parameter
scenario, but without more details from the OP, it's hard to know for
sure, since we don't know how the three-parameter scenario differs from
the two-parameter scenario (i.e. is it completely different, or does the
three-parameter scenario somehow resolve down to pairs of the
two-parameter scenario).

Hopefully the OP will provide some additional details that actually do
elaborate on the problem. :)

Pete
Jun 27 '08 #10
Hi Peter.. I agree it is difficult to solve a puzzle without all the
pieces.

For n metals, it _might_ be possible to SWITCH on the SUM OF ATOMIC
NUMBERS especially if this results in no mathematical duplicates for a
given
combination of n metals of atomic numbers in the domain of
{1,3,11,19,37,55,87}. So IAlkaliMetal inherits from IElement and:

int IElement.GetAtomicNumber() as readonly property.

Regards,
Jeff

*** Sent via Developersdex http://www.developersdex.com ***
Jun 27 '08 #11
On Wed, 16 Apr 2008 21:05:41 -0700, Jeff Louie <an*******@devdex.com
wrote:
Hi Peter.. I agree it is difficult to solve a puzzle without all the
pieces.

For n metals, it _might_ be possible to SWITCH on the SUM OF ATOMIC
NUMBERS especially if this results in no mathematical duplicates for a
given
combination of n metals of atomic numbers in the domain of
{1,3,11,19,37,55,87}. So IAlkaliMetal inherits from IElement and:

int IElement.GetAtomicNumber() as readonly property.
Heh. Well, you're on the right track. :)

I wouldn't bother with using the actual atomic number though. In spite of
the name, we're really just talking about C# classes here. :) It would
be simple enough to define a "flags" enumeration where each member of the
enumeration corresponds to one of the classes/elements.

Then the readonly property you suggest would just return that, and you'd
switch on the combination of two or more of the flags:

[Flags]
enum MetalID
{
Li = 1, Na = 2, K = 4, Rb = 8, Cs = 16, Fr = 32
}

class Li : IAlkaliMetal
{
public MetalID MetalID { get { return MetalID.Li; } }
}

// etc.

void Combine(IAlkaliMetal metal1, IAlkaliMetal metal2)
{
switch (metal1.MetalID | metal2.MetalID)
{
case (MetalID.Li | MetalID.Li):
CombineLiAndLi(metal1, metal2);
break;
case (MetalID.Li | MetalID.Na):
CombineLiAndNa(metal1, metal2);
break;
// etc.
}
}

It's not really less typing, but it's perhaps more representational of
what's going on, and should be at least somewhat computationally more
efficient.

Of course, this is fun, but until we get more details who knows whether
it's really a useful approach. :)

Pete
Jun 27 '08 #12
Tem
>if(elem1is Li && elem2 is Li)
> Combine(((Li)elem1),((Na)elem2);

If elem2 is Li, why are you casting to Na?
That's a typo. sorry. should be Combine(((Li)elem1),((Li)elem2);
>
It's well and good to simplify your code examples, but you still need to
make sure that they are correct and compilable. I will assume that you
simply meant to write Li instead of Na here, and that you didn't intend
to leave off the required paren at the end of each method call in your
example.
sorry. typo.
>
That said, you still haven't really explained what these methods do. If
each possible combination really represents some different operation,
then I don't see any way out of at some point having to channel the flow
of execution down to one of those possible operations. If the
operations are specific to the combinations of the elements, then you
will at some point need some kind of comparison to resolve the
combinations into individual operations.
I haven't figured out what each Combine method will do. That's going to
be my next task. But I do want to structure my program correctly so that
I can add more code easily later and keep good maintainability.

The method Combine will perform totally different operations depending
on input type.
>
It's possible that you could represent these combinations in a table,
with delegates representing each method that handles the combination.
Then rather than having a bunch of if/else if statements, you could
search the table for the combination in question.
This sounds like a possible solution. Not sure how I would construct
such table and how to use delegates.
>
As far as extending this to combinations of three, again...what does
this operation do? With 216 combinations, do you really have 216
different methods you might call?
Yes with three inputs there will be 216 unique methods.

Thank you.
Jun 27 '08 #13
Tem
I thought of this as a possible solution but

someAlkaliMetal1.Combine(someAlkiliMetal2)

The Combine method in instance someAlkaliMetal1 would still need to
check the type of someAlkiliMetal2

Off the top of my pointed head. Each AlkaliMetal _could_ implement
IAlkiliMetal.Combine as an instance method
someAlkaliMetal.Combine(someAlkiliMetal). So a particular metal would
presumably know how to combine with any other metal including itself.

The static method CombineAlkiliMetals(someAlkiliMetal,someAlkiliMeta l)
could
simply checks for null parameters and then calls the appropriate
instance
method someAlkiliMetal.Combine. I can see a downside in duplication of
code
for am1.Combine(am2) and am2.Combine(am1), which, presumably, would have
the same implementation.

Regards,
Jeff

*** Sent via Developersdex http://www.developersdex.com ***
Jun 27 '08 #14
Tem
I was just think the same.

This is what a 3 input parameter scenario would look like, again, each
Combine method does different things

Public Void PrepareCombine(IAlkaliMetal elem1, IAlkaliMetal elem2,
AlkaliMetal elem3)
{
if(elem1 is Li && elem2 is Li && elem3 is Li)
Combine(((Li)elem1),((Li)elem2),((Li)elem3));
else if(elem1 is Li && elem2 is Li && elem3 is Na)
Combine(((Li)elem1),((Li)elem2),((Li)elem3));
else if(elem1 is Li && elem2 is Li && elem3 is K)
Combine(((Li)elem1),((Li)elem2), ((K)elem3));...
}
Peter Duniho wrote:
On Wed, 16 Apr 2008 19:34:25 -0700, Jeff Louie <an*******@devdex.com>
wrote:
>Off the top of my pointed head. Each AlkaliMetal _could_ implement
IAlkiliMetal.Combine as an instance method
someAlkaliMetal.Combine(someAlkiliMetal). So a particular metal would
presumably know how to combine with any other metal including itself.

But would still have to check the type of the passed in object. Making
it an instance method might help with respect to breaking the problem
down into smaller, easier-to-manage parts. But it wouldn't reduce the
total number of type checks.

There's also a potential issue with respect to the three-parameter
scenario, but without more details from the OP, it's hard to know for
sure, since we don't know how the three-parameter scenario differs from
the two-parameter scenario (i.e. is it completely different, or does the
three-parameter scenario somehow resolve down to pairs of the
two-parameter scenario).

Hopefully the OP will provide some additional details that actually do
elaborate on the problem. :)

Pete
Jun 27 '08 #15
Tem
Yes it really is just a c# question

How to redirect to the overload method with the correct parameters
(without using if obj is type else if...)

Jun 27 '08 #16
On Wed, 16 Apr 2008 23:04:56 -0700, Tem <te*****@yahoo.comwrote:
[...]
I haven't figured out what each Combine method will do. That's going to
be my next task. But I do want to structure my program correctly so that
I can add more code easily later and keep good maintainability.
I really do not believe that you can address the broader question until
you actually know what each method will do. It's entirely possible that
once you figure out what the method will do, that you find that you need
only one method anyway.
The method Combine will perform totally different operations depending
on input type.
"Totally different" implies that there is literally _no_ similarity
between the operations of each method. For example, perhaps when you
combine Li and Li, you open a new dialog box and as the user what his
favorite color is. But when you combine Li and Na, you load a .WAV file
and play the sound within.

Surely there is _some_ relationship between what the method does
regardless of the inputs. It seems entirely plausible to me that whatever
the difference, it could be driven by the data within each object, rather
than by the type itself. It's even possible this could simply be one
single instance method in an _abstract_ AlkaliMetal class, so that all of
your AlkaliMetal implementations share the same implementation.

Heck, it's possible that the base AlkaliMetal class doesn't even need to
be abstract. I mention abstract simply because that's the closest
equivalent to an interface, but so far you haven't demonstrated a need for
the interface itself. I think it's possible that all you really need is a
single base class to implement shared functionality.
> It's possible that you could represent these combinations in a table,
with delegates representing each method that handles the combination.
Then rather than having a bunch of if/else if statements, you could
search the table for the combination in question.

This sounds like a possible solution. Not sure how I would construct
such table and how to use delegates.
The easiest way to construct it is make it a static member of a class, as
an array of structures declared to contain the data you want (e.g.
combinations and delegates matching each combination). Then you can
either search the table for the right combination each time, or iterate
the table once, adding all the data to a dictionary for faster access.

But so far I remain unconvinced that you really have a need for any of
this.
> As far as extending this to combinations of three, again...what does
this operation do? With 216 combinations, do you really have 216
different methods you might call?

Yes with three inputs there will be 216 unique methods.
That just doesn't seem plausible. 216 completely unique methods -- that
is, with absolutely no similarities in operation at all -- all with the
same name, all operating on classes that share the same interface? I'd
have to see it to believe it.

Pete
Jun 27 '08 #17
On Wed, 16 Apr 2008 23:27:22 -0700, Tem <te*****@yahoo.comwrote:
Yes it really is just a c# question

How to redirect to the overload method with the correct parameters
(without using if obj is type else if...)
Unless the parameters are already typed, the only way is with virtual
methods, and that will only address one of the parameters at most, since
it would work by being an instance method on one of what's a parameter now.

Other than that, you don't.

But really, I am skeptical that you really need what you think you need.

Pete
Jun 27 '08 #18

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Jacob Jensen | last post: by
3 posts views Thread by DJ.precario | last post: by
9 posts views Thread by Roman Mashak | last post: by
3 posts views Thread by Steve Teeples | last post: by
11 posts views Thread by Frederic Rentsch | last post: by
5 posts views Thread by Ronald Raygun | last post: by
4 posts views Thread by Wally Barnes | last post: by
reply views Thread by XIAOLAOHU | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.