Polymorphism and GetType()

  • Thread starter Thread starter .pd.
  • Start date Start date
P

.pd.

Hello,

I'm trying to setup a named-object list using objects of 3 different
types all derived from the same base class.

public class namedObjectList :
System.Collections.Specialized.NameObjectCollectionBase
{
public BaseType this[string name]
{
get { return BaseGet(name); }
}

public void Add(string key, BaseType obj)
{
BaseAdd(key, obj);
}
}

I then have my 3 derived types:

public class Derive1 : BaseType {...}
public class Derive2 : BaseType {...}
public class Derive3 : BaseType {...}

I can add instances of these 3 derived types with no problem but when I
do this:

string s = myNamedObjectList["whatever"].GetType().Name

I get back "BaseType" when what I really wanted was whichever one of the
derived types was added.

Should this work? How can I get what I want?

Thanks for any help,

..pd.
 
Hi .pd,
GetType returns the real type of the object not the type of the variable
used to reference the object. In other words it has to work for you. Are you
sure your BaseGet(...) method works correctly?

B/rgds
100
 
100 wrote on Wed 17 Dec 2003 05:58:56p:
Hi .pd,
GetType returns the real type of the object not the type of the
variable used to reference the object. In other words it has to work
for you. Are you sure your BaseGet(...) method works correctly?

So you're telling me I have write my own GetType()? I was afraid of that.

BaseGet() is a method belonging to the
System.Collections.Specialized.NameObjectCollectionBase class. It ain't
mine.

..pd.
 
..pd. said:
100 wrote on Wed 17 Dec 2003 05:58:56p:


So you're telling me I have write my own GetType()? I was afraid of that.

No, you *can't* write your own GetType, but 100 was saying (correctly)
that if GetType().Name is returning "BaseType" then the object in
question really *is* an instance of *just* BaseType, and not a derived
type.

Please give a short but complete example which shows the problem you're
having. See
http://www.pobox.com/~skeet/csharp/complete.html for what I mean by
that.
 
The Add() method in my NameObjectCollectionBase inheritor had no overloads
and accepted an instance of the base type as its argument.

By replacing this with an overload for each derived type, it now works as I
expected.

Thanks for your responses,

..pd.
 
..pd. said:
The Add() method in my NameObjectCollectionBase inheritor had no overloads
and accepted an instance of the base type as its argument.

That should make no difference though, as each derived type *is* an
instance of the base type.
By replacing this with an overload for each derived type, it now works as I
expected.

Really not sure what you mean here, but never mind - I'm glad you've
got it working.
 
Hi .pd,

I tried NameObjectCollectionBase and it works fine for me. I wrote only one
Add method with the parameter of the base class and it returns correct class
names of the entries as expected.

However, unlike Hashtable and DictionaryBase
System.Collections.Specialized.NameObjectCollectionBase allows you to have
more then one entry in the collection with the same name (key). In this case
BaseGet method returns always the first one. So my guess is that due to some
error in your code you add all objects under the same name (key) and/or read
the same key regardless what you pass as a object name to your get method.
In those cases if first elemet added in the collection is of type BaseType
it will return the same object over and over again. So check how you
generate the names for the objects.
Anyway, I'm little confused that adding overloads for the Add method solves
your problem. So my next guess is that you make some kind of cloning the
objects before adding them to the collection.
For example.

class Base: ICloneable
{
public object Clone()
{
return new Base(); //Clone the object
}
}

class Deriv1:Base, ICloneable
{
public object Clone()
{
return new Deriv1(); //Clone the object
}
}

and then you have

public void Add(string name, Base obj)
{
base.BaseAdd(name, obj.Clone());
}

This will lead to the results you had. The type of the objects in the
collection will always be Base.
Ofcourse the compiler thorws warning message and underlines Deriv1.Cone
method. But there are some situations where you can miss those hints.

The fact that you had those problems means that there is something wrong in
your code.

HTH
B\rgds
100
 
100 wrote on Thu 18 Dec 2003 03:07:26p:
The fact that you had those problems means that there is something
wrong in your code.

Yeah. Jiggered if I know what though.

Jon Skeet [C# MVP] wrote on Thu 18 Dec 2003 12:18:21p:
That should make no difference though, as each derived type *is* an
instance of the base type.


Really not sure what you mean here, but never mind - I'm glad you've
got it working.

Yeah it's weird. I wrote a reproducer but it didn't reproduce ;-)

I also reverted to a single constructor taking the base type and that
then worked. Obviously, I did something different the previous time but
failed to notice it.

I've included my sample code (which, as I say, works fine) purely as a
matter of record.

Cheers,
..pd.

// ---------8<-------------
using System;
using System.Collections;

namespace foo
{
public class myList :
System.Collections.Specialized.NameObjectCollectionBase
{
public myBase this[string name]
{
get
{
return (myBase) BaseGet(name);
}
}

// changing this to an overload for each specific inheritor of myBase
// fixed the original problem.
// public void Add(string s, myDerived1 b) {}
// public void Add(string s, myDerived2 b) {}

public void Add(string s, myBase b)
{
BaseAdd(s, b);
}

}
public class myBase
{
}
public class myDerived1 : myBase
{
}
public class myDerived2 : myBase
{
}
public class pd
{
public static void Main()
{
myList ml = new myList();

ml.Add("fred", (myBase) new myDerived1());
ml.Add("barny", (myBase) new myDerived2());

Console.WriteLine(ml["fred"].GetType().Name);
Console.WriteLine(ml["barny"].GetType().Name);

}
}
}
 
Back
Top