-
Multiple Inheritance and Casting
I have a circumstance where multiple inheritance is required. I have a class layout something like the following.
Code:
class Mode
{
}
class ModeType1 : Mode
{
}
class ModeType2 : Mode
{
}
class SpecialModeCommon
{
}
class SpecialModeType1 : ModeType1, SpecialModeCommon
{
}
class SpecialModeType2 : ModeType2, SpecialModeCommon
{
}
class ModeManager
{
static Mode* GetMode();
}
Now, I need to use GetMode() to access the mode but I need to cast it to SpecialModeCommon in order to access some of the special methods/objects. At the point where I am doing this I can be sure that the Mode is also of type SpecialModeCommon.
The following will not compile since SpecialModeCommon does not extend Mode.
Code:
SpecialModeCommon* mode = static_cast<SpecialModeCommon*>(ModeManager::GetMode());
I can do a C style cast to get it to compile but that results in data being written to odd places and things not working.
For some reason not understood by me, dynamic_cast does not work in the environment I am working in. I don't understand why but assume I don't have dynamic_cast available (would that even solve this problem?)
Any assistance would be appreciated.
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
Eggman002
I have a circumstance where multiple inheritance is required.
Note that class uses private inheritance by default. To get public inheritance you need to declare that explicitly, like
Code:
class ModeType1 : public Mode
And try to avoid downcasting if you can.
-
Re: Multiple Inheritance and Casting
Well, look at your return type. It's a "Mode" pointer, totally unrelated to a "SpecialMode" pointer. What if your ModeManager has regular Mode objects (nothing inherited from SpecialModeCommon)?
I haven't looked into it too deeply, but my guess is that your mode manager is storing modes only. dynamic_cast has no way of knowing if any of the modes stored are pointers to objects that are derived from SpecialMode.
If you cannot re-factor this data structure, perhaps you could create a "GetSpecialMode" function, and add a data member to your ModeManager that stores SpecialMode objects. Or, create a "SpecialModeManager"?
Viggy
-
Re: Multiple Inheritance and Casting
Quick answer
You can't do what you're trying here because SpecialModeCommon is not a Mode and Mode is not a SpecialModeCommon.
The quick fix is make SpecialModeCommon inherit from Mode thus removing the need for multiple inheritance.
Explanation
Think of inheratance a different way for a second.
Code:
class A {};
class B : public A {};
// ...
B * SomeB;
A * SomeA = SomeB;
is implamented as
Code:
class A{};
class B {
A inheratedA;
};
// ...
B * SomeB;
A * SomeA = &(SomeB->inheratedA);
Now for something more complicated:
Code:
class A {};
class B {};
class C {};
class Test1 : A, B, C {};
class Test2 : A, C {};
Gets Implamented as
Code:
class A {};
class B {};
class C {};
class Test1 {
A InheritedA;
B InheritedB;
C InheritedC;
};
class Test2 {
A InheritedA;
C InheritedC;
};
With this you can go from Test1 to C (change the memory pointer to point to "inheratedC").
You can also go from C to Test1 easily (assume the pointer points to inheratedC so change it to point to the start of the object).
But you can not go from A to C.
How would you get there?
Is there a B inbetween or not?
The compiler simply doesnt know.
If you use C-style casting you can get it to compile, but the compiler wont change the pointer when you cast so it will read/write to the wrong fields.
Hope this is of some help.
Regards
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
_uj
Note that class uses private inheritance by default. To get public inheritance you need to declare that explicitly
That was just due to a sloppy rewrite of the code. I was using public.
As for the rest of the comments, that is sort of what I figured and yet I am not sure there is a nice way to change around the application. I have thought about having SpecialModeCommon inherit from Mode but then I end up with a diamond pattern for my inheritance tree where two branches of the inheritance both inherit from Mode. That has it's own set of issues.
It doesn't entirely solve the problem but suppose I were to take the result of GetMode and cast it to SpecialModeType1 (Where the returned mode is actually of type SpecialModeType1) and then from there cast it again into SpecialModeCommon (which should now be a valid cast). Would something like that work? Doing that defeats the purpose of having SpecialModeCommon but I am just curious if it would work.
Now if I was writing this in C#, the equivalent would be if SpecialModeCommon was an Interface. In this case I believe C# would let me do the cast something like:
Code:
ISpecialModeCommon m = ModeManager.GetMode() as ISpecialModeCommon;
if(m != null)
{
// m must be of type ISpecialModeCommon
}
or
Code:
Mode m = ModeManager.GetMode();
if(m is ISpecialModeCommon)
{
ISpecialModeCommon sm = mode as ISpecialModeCommon
}
Does C++ not have anything equivalent?
-
Re: Multiple Inheritance and Casting
You can use dynamic_cast to try downcasting.
Code:
ISpecialModeCommon* m = dynamic_cast<ISpecialModeCommon*>( ModeManager.GetMode() );
if( NULL != m )
{
// do something with m
}
Edit:
Typo fixed
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
Eggman002
and yet I am not sure there is a nice way to change around the application.
I think this is the wrong approach. Instead think about what the different types (classes) represent and what relationships you want to express. What are all these "modes" you're trying to fit into an inheritance hierarchy?
And in principle a downcast represents a design failure so try to avoid that. Checking objects for type and then make special provisions based on type is bad design (in C++ as well as in C#).
-
Re: Multiple Inheritance and Casting
Sorry for posting an off topic response, but couling, you do not have private messaging enabled... anyway, you are missing an 'e' off of coffee in your signature.;)
Eggman002, I understand why your structure is the way it is, but at the same time I don't like it. Although you could argue that your structure has an is-a relationship, in my opinion is smacks as a structure designed for code re-use.
I would seriously reconsider your design. What is the difference in functionality between ModeType1 and ModeType2 for example?
-
Re: Multiple Inheritance and Casting
Examples of code that need a class design such as you're suggesting are very rare. Most people considder them bad design.
Having never used them myself I'm going to tentatively suggest using a virtual base class.
Beyond this, a design really can't be sudgested as it isnt clear why you chose this design. If you'd like a hand with re-factoring then you will need to share a little more infomation about your constraints (the reason why you chose this design based on what you're trying to build)
Regards
_____________________________________
PredicateNormative:
couling <-- dyslexic. But thanks for letting me know.
-
Re: Multiple Inheritance and Casting
I have to agree with the others in that this appears to be an abuse of inheritance. Whanting to eliminate code duplication is never a reason for public inheritance.
This seems more like a situation that would use aggregation/composition.
I did want to point out that couling's post with the use of members instead of inheritance is a good one, and that there IS a way to reliabily "get from A to C" regardless of if the instance is a Test1 or Test2....
Simple create a singleton map that std::map<A*,C*> and have your classes register the apppropriate addresses in the map (dont forget to unregister in the destructor!!!
Now you can quickly see if "An instance of A has a related instance of C"
-
Re: Multiple Inheritance and Casting
Well suffice it to say that I didn't write all the code, I just have to modify it.
So in my example, Mode, ModeType1, ModeType2 and ModeManager are written by someone else and can not be easily modified without potentially breaking everything.
I have created SpecialModeType1 and SpecialModeType2 to provide some increased functionality above and beyond what is in ModeType1 and ModeType2.
These two special modes have common functions so it seems like they should inherit from a common source.
Basically I am trying to avoid having to to something like:
Code:
if(verify that we are in SpecialMode1)
{
// Access Data from SpecialMode1
}
else if(verify that we are in SpecialMode2)
{
// Access Data From SpecialMode2
}
Instead I want to do:
Code:
if(verify that we are in SpecialMode1 or SpecialMode2)
{
// Access Data From SpecialModeCommon
}
-
Re: Multiple Inheritance and Casting
All comments in this post refer to public inheritance...
Quote:
Originally Posted by
Eggman002
These two special modes have common functions so it seems like they should inherit from a common source.
No, no, no... Now go to your blackboard, pick up some chalk, and write 100 times "I will never think about using inheritance to share code".
Inheritcance is for strictly IS-A relationships. Presuming you have comprehensive documentation on all of the classes, you MUST be able to take all of the documentation for both SpecialModeCommon, Mode, and ModeType1
then do a search/replace with SpecialModeType1 in the three sets of documents.
If the resulting three documents contain a single inaccuracy, then either your documentation is wrong, or inheritance is NOT appropriate.
If you want to "share implementation" then use aggregation:
psuedo code...
Code:
class SpecialModeCommon
{
public:
void ACommonFunction() {}
}
class SpecialModeType1 : ModeType1
{
private:
SpecialModeCommon m_Common;
public:
void ACommonFunction()
{
m_Common.ACommonFunction();
}
}
SpecialModeType2 : ModeType2
{
private:
SpecialModeCommon m_Common;
public:
void ACommonFunction()
{
m_Common.ACommonFunction();
}
}
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
TheCPUWizard
If you want to "share implementation" then use aggregation:
psuedo code...
Code:
class SpecialModeCommon
{
public:
void ACommonFunction() {}
}
class SpecialModeType1 : ModeType1
{
private:
SpecialModeCommon m_Common;
public:
void ACommonFunction()
{
m_Common.ACommonFunction();
}
}
SpecialModeType2 : ModeType2
{
private:
SpecialModeCommon m_Common;
public:
void ACommonFunction()
{
m_Common.ACommonFunction();
}
}
The problem with that solution (unless I am missing something) is that I then have to do the following:
Code:
if(Verify we are in SpecialModeType1)
{
SpecialModeType1* mode = static_cast<SpecialModeType1*>(ModeManager::GetMode());
mode->ACommonFunction();
}
else (Verify we are in SpecialModeType2)
{
SpecialModeType2* mode = static_cast<SpecialModeType2*>(ModeManager::GetMode());
mode->ACommonFunction();
}
Now it might just be me but it seems like the fact that I have the same line of code repeated is silly (i.e. mode->ACommonFunction()).
In a simple example like this it isn't a big deal but in a more complex example where this code may be getting called in many places and may be calling more than just one common function, this could get messy.
I suppose it doesn't matter since that is essentially what I wound up having to do in order to get it to work, but it seems wasteful.
-
Re: Multiple Inheritance and Casting
The problem is that this isnt really possible. The best sugestion for what you want was to create a map (as suggested by TheCPUWizard earlier).
You need a way to get from a Mode to SpecialModeCommon. This can not be done directly with inheritance unless either you can edit the Mode class or you work out the precise type of object.
So the only option left to you is to create a map (lookup) between objects of type Mode and objects of type SpecialModeCommon.
________________________________________________________________
Another option is a seriously DIRTY HACK.
reorder the multiple inheritance to put SpecialModeCommon first
making a dummy class to cast to that inherits from both SpecialModeCommon and Mode.
I just know I'm going to get flamed for even suggesting that one.
I certainly would hate to know that any software I use is based on it.
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
Eggman002
The problem with that solution (unless I am missing something) is that I then have to do the following:
....
Not at all. You implement the method on the class, and it redirects, you NEVER perform a cast.
Quote:
I suppose it doesn't matter since that is essentially what I wound up having to do in order to get it to work, but it seems wasteful.
Writing "correct" programs is not about the effort that you have to put in. It is about properly expressing the actual intended relationships.
If one has 100 classes that do not conceptually fully support the IS-A (eg 1 out of 1000 use cases would be incorrect), then the appropriate (IMPO) approach is to put the functionallity in a common class and aggregate it, putting "forwarding" methods in each of the individual classes (or possibly at some lower level VALID common IS-A point)
To avoid duplication, and maintenance issues, I will (note: .inh is an extension I use to indicate a file that is meant to be included at some point in other .h file, but never to be directly included in a .cpp)
Code:
//commn.inh
{
void F1() {m_Common.F1();
void F2() {m_Common.F2();
void F3() {m_Common.F3();
}
//sample_class.h
//that needs to support the common behaviour but does not represent IS-A
class SomeClass
{
public:
void MyCursomMethos();
#include "common.inh"
}
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
TheCPUWizard
Not at all. You implement the method on the class, and it redirects, you NEVER perform a cast.
What about when implementing the method on the class doesn't make sense (or is impossible). For example what if you are inheriting from a class where you don't have the source (i.e. from a code library or something). Or what about something like:
Code:
class Person
{
...
}
class Banker : Person
{
}
class BasketballPlayer : Person
{
int GetPointsPerGame();
}
Now suppose you have a "Person" object and you know it is a BasketballPlayer object (for various reasons). You need to call the GetPointsPerGame.
Obviously you shouldn't just put "GetPointPerGame" into the Person class since that doesn't make sense. The only way to get the info you need is to cast it to a BasketballPlayer.
I realize this example is a bit arbitrary, but it illustrates my question fairly well. It seems like you are suggesting that casting should always be avoided, yet there are cases where it seems to me it is necessary.
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
Eggman002
Now suppose you have a "Person" object and you know it is a BasketballPlayer object (for various reasons). You need to call the GetPointsPerGame.
The question is directly related to "HOW" you know the Person is a basketball player, and "WHY" you would be iterating through a collection of "People" where you only want to do something for Basketball players.
Consider if you wanted to know the average points per game globally....Would you take the "world census" (billions of people), look at each persons "job description" and then gather the data?
I rather tend to doubt it. Rather you would go to some specific collection (NBA Team roster?) and use that as your source.
In other words, the very model you used as your illustration seems to be very poorly designed - and maybe the actual program is also.
btw: Regarding the "dont have source", this often means using aggregation/composition along with the adapter patterns instead of derivation...
-
Re: Multiple Inheritance and Casting
So I am revisiting this issue and I wonder what people think about the following solution. Is it appropriate? Is it good design?
To avoid multiple inheritance, I use the following setup:
Code:
class Mode
{
}
class ModeType1 : Mode
{
}
class ModeType2: Mode
{
}
class SpecialModeType1: ModeType1
{
}
class SpecialModeType2: ModeType2
{
}
Then to assist with code reuse and to avoid having to wrap everything in an if statement or a switch statement I do the following:
Code:
class SpecialModeCommon
{
static void ACommonFunction(Mode currentMode)
{
if(Verify we are in SpecialMode1)
{
SpecialModeType1* mode = static_cast<SpecialModeType1*>(currentMode);
...
Access any values required and assign them to variables
...
}
else if(Verify we are in SpecialMode2)
{
SpecialModeType2* mode = static_cast<SpecialModeType2*>(currentMode);
...
Access any values required and assign them to variables
...
}
...
Do any processing on the common values.
...
}
}
This means I don't have to worry about multiple inheritance issues. I can still reuse most of the code (except for the accessors which will have to be written for each mode).
-
Re: Multiple Inheritance and Casting
I can not recommend in favor of ANY design which involves run time checking of types.
I also want to repeat that code re-use is NEVER a reason for utilizing inheritance.
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
TheCPUWizard
I can not recommend in favor of ANY design which involves run time checking of types.
There is no runtime checking of types happening here. That was not clear in the sample. There is runtime checking of a flag which indicates which mode we are currently in.
Though the flag is not much better than checking the type (Better performance but not necessarily better design), this framework is heavily used in the code base that I am working on and I can not change that. So in this case I would rather stick to the existing framework for consistency rather than have multiple ways of doing things.
I suppose a better way to handle this would be to have a ModeManager to handle all Modes and then a SpecialModeManager to handle SpecialModes. The SpecialModes would be included in both ModeManagers but if I wanted only the SpecialModes I can go to the SpecialModeManager. Or something like that. But again in the framework I am working with this would be a huge departure from how everything else is implemented. And if I were to do this I would still be checking the above mentioned flag to figure out whether to go to ModeManager or SpecialModeManager so the only thing I am saving is having to to a static_cast.
I would still be interested in hearing and discussing the "correct" solution though for future reference.
Quote:
Originally Posted by
TheCPUWizard
I also want to repeat that code re-use is NEVER a reason for utilizing inheritance.
Inheritance was not used for code re-use in the above example. SpecialModeCommon does not inherit from anything and nothing inherits from SpecialModeCommon. A static function was created for code re-use.
-
Re: Multiple Inheritance and Casting
Why not just use"double dispatch" and be done with it?????:confused::confused:
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
TheCPUWizard
Why not just use"double dispatch" and be done with it?????:confused::confused:
Sorry, I am not overly familiar with the concept of Double Dispatch. I Googled it but I am not really sure how it would apply here.
-
Re: Multiple Inheritance and Casting
Code:
class Foo
{
void Execute(Bar1 &b) {cout << "Processing a Bar1"; }
void Execute(Bar2 &b) {cout << "Processing a Bar2"; }
void Execute(Bar &b) { b.Dispatch(this) }
}
class Bar
{
virtual void Dispatch(Foo &f) { f.Execute(this); }
}
class Bar1: Bar
{
virtual void Dispatch(Foo &f) { f.Execute(this); }
}
class Bar2: Bar
{
virtual void Dispatch(Foo &f) { f.Execute(this); }
}
int main()
{
Bar *b = new Bar2();
Foo f;
f(*b);
}
Foo will process the CORRECT Bar2 routine.
-
Re: Multiple Inheritance and Casting
On a related note, you might want to search for "visitor pattern".
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
TheCPUWizard
I also want to repeat that code re-use is NEVER a reason for utilizing inheritance.
I've come across a template technique that appears to use inheritance for code reuse. What are your opinions on this?
Or do you consider that Communicator doesn't break the IS-A rule in this case?
Code:
class Printer
{
public:
virtual void Print() = 0;
};
class Console_Printer : public Printer
{
public:
void Print();
}
class Stream_Printer : public Printer
{
public:
void Print();
}
class Comms
{
public:
virtual void Send() = 0;
};
class Serial_Comms : public Comms
{
public:
void Send();
};
class Net_Comms : public Comms
{
public:
void Send();
};
template <typename TComms, typename TPrinter>
class Communicator : public TComms, public TPrinter
{
};
int main()
{
Communicator<Net_Comms, Console_Printer> communicator;
Communicator<Serial_Comms, Stream_Printer> communicator2;
communicator.Send();
communicator2.Print();
}
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
Eggman002
Sorry, I am not overly familiar with the concept of Double Dispatch. I Googled it but I am not really sure how it would apply here.
Hello Eggman002
Just in case you want it
http://en.wikipedia.org/wiki/Design_...puter_science)
and this might help too...just in case
http://en.wikipedia.org/wiki/Open/closed_principle
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
JohnW@Wessex
I've come across a template technique that appears to use inheritance for code reuse. What are your opinions on this?
Or do you consider that Communicator doesn't break the IS-A rule in this case?
In my view, it does NOT break the IS-A rule, in fact it conveys the "IS-both-A" for each of the template arguments. Of course it does open up the various issues which occur when multiple inheritance of concrete classes is introduced into an application...
One thing (which may be in the real implementations that got purged from the sample) that I would "expect" is that communicator provided some "communication" betweeen the two template parameter classes.
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
TheCPUWizard
One thing (which may be in the real implementations that got purged from the sample)
No, I just made it up on the fly. I haven't actually used this technique. I think it was described as implementing 'policies', in that a concrete class could be made up from different building blocks, each block implementing a 'policy'. I'm not sure that they were expected to always 'know' about each other, but just provide a set of independent implementations.
Sort of compile time 'Dependency Inversion Principle'?
-
Re: Multiple Inheritance and Casting
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
JohnW@Wessex
No, I just made it up on the fly. I haven't actually used this technique. I think it was described as implementing 'policies', in that a concrete class could be made up from different building blocks, each block implementing a 'policy'. I'm not sure that they were expected to always 'know' about each other, but just provide a set of independent implementations.
Sort of compile time 'Dependency Inversion Principle'?
Taken directly from the first paragraph of the link tht John provided:
Quote:
The central idiom in policy-based design is a class template (called the host class), taking several type parameters as input, which are instantiated with types selected by the user (called policy classes), each implementing a particular implicit interface (called a policy), and encapsulating some orthogonal (or mostly orthogonal) aspect of the behavior of the instantiated host class.
-
Re: Multiple Inheritance and Casting
Quote:
and encapsulating some orthogonal (or mostly orthogonal) aspect of the behavior of the instantiated host class.
Would you be able to expand on this in POE (Plain Old English)
I'm not entirely sure I understand the meaning of 'orthogonal' in this context. :confused:
(orthogonal usually means "at right angles to")
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
JohnW@Wessex
Would you be able to expand on this in POE (Plain Old English)
I'm not entirely sure I understand the meaning of 'orthogonal' in this context. :confused:
(orthogonal usually means "at right angles to")
John,
I am suprised that someone would post a link to material for reference when they have problems understanding the first paragraph of the linked material.. :eek:
Simply draw a diagram, inheritance is represented by vertical lines. A reference between peer classes as a horizontal line. Definately "right angles".
In the code sample that was posted, one would presume that the Printer classes knew how to convert "content" to "byte patterns: that would be understood by a given printer, and the Comm class would know how to transfer bytes across a media (USB, Serial, etc).
Therefore the Template class would typically implement the functionallity of taking the bytes output by the printer (base class #1) and passing them to the communications (base class #2).
-
Re: Multiple Inheritance and Casting
Okay looking in further detail at the Double Dispatch idea, I still don't really see how I can make use of it. At least not with the current code base (which I am stuck with).
Looking at the Foo/Bar example, I would think my "Modes" in this case would be the "Bar" classes, and then the objects which use the Modes would then be the "Foo" class (assuming I follow correctly).
One problem in my situation is that the Foos out number the bars by far. There are potentially hundreds of different locations where I need to call functions on the modes. So defining multiple functions in each of those locations gets quite time consuming and annoying.
Another problem is that in the examples that I have looked at, the base class has the same members as the child class. This is not the case in my situation. For my situation the SpecialMode classes have methods unique to those modes. So I need to access it as a "SpecialMode" in order to access those methods.
However I feel like maybe I am missing something with the Double Dispatch.
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
Eggman002
One problem in my situation is that the Foos out number the bars by far. There are potentially hundreds of different locations where I need to call functions on the modes. So defining multiple functions in each of those locations gets quite time consuming and annoying.
But that is a "fact of life". If I add a capability to a few hundred classes (my industrial automation library has over 5000 different control elements) and there is no direct relationship between them (IS-A), then it DOES mean going into a few hundred files and adding the code.
Now in many cases this can be minimized. If you have a group of conceptually related methods which by definition have a common grouping (but not an inheritance relationship), then simply use a #include to simplify the legwork..
-
Re: Multiple Inheritance and Casting
Quote:
I am suprised that someone would post a link to material for reference when they have problems understanding the first paragraph of the linked material.. :eek:
I just googled for "c++ template policy" and that link popped up first. I understood the concepts described, it was just the word 'orthogonal' was unfamiliar for me in a programming context. Seems obvious now :thumb:
-
Re: Multiple Inheritance and Casting
Quote:
Originally Posted by
TheCPUWizard
But that is a "fact of life". If I add a capability to a few hundred classes (my industrial automation library has over 5000 different control elements) and there is no direct relationship between them (IS-A), then it DOES mean going into a few hundred files and adding the code.
Now in many cases this can be minimized. If you have a group of conceptually related methods which by definition have a common grouping (but not an inheritance relationship), then simply use a #include to simplify the legwork..
Actually I think I understand a way that I can use this technique now that I have thought about it a bit. As per my previous example if I have a SpecialModeCommon, then I can use the SpecialModeCommon as a wrapper so that I have something like this:
Code:
class SpecialModeCommon
{
public:
static void ACommonFunction(SpecialModeType1 mode)
{
// Process SpecialModeType1
ACommonFunctionCommonCode(...);
}
static void ACommonFunction(SpecialModeType2 mode)
{
// Process SpecialModeType2
ACommonFunctionCommonCode(...);
}
private:
static void ACommonFunctionCommonCode(...)
{
// Common Code goes here.
}
}
Then elsewhere if I need to call ACommonFunction I can just do:
SpecialModeCommon::ACommonFunction(mode);
And it should call the correct function and do the processing correctly. And in my hundreds of locations I only need to put one line of code.
I like this solution. It doesn't require any special casting or checking of types at runtime. I can re-use a fair amount of the code.
Thanks for all the help.