473,657 Members | 2,458 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Polymorphism & Collections

I'm relatively new to C# and polymorphism, so what I'm trying to accomplish
may not be possible, or there may be a totally different approach that I
should be taking.

I have a base class (MyBase) and a collection of MyBase objects
(MyBaseCollecti on). Now, I also have an extension to MyBase (MyExtendedBase
: MyBase) that has additional properties. And lastly, I have a collection
of MyExtendedBase objects(MyExten dedBaseCollecti on : MyBaseCollectio n).

I have a data layer that has a method (GetMyBaseColle ction) that retrieves
records from the database, and populates a MyBaseCollectio n with these
records. However, there are cases where I need to use this method to
populate a MyExtendedBaseC ollection. But here's the catch -- I want my data
layer to be unaware (and independent) of MyExtendedBase and
MyExtendedBaseC ollection.

I have tried several different ways to accomplish this, but no matter what I
do, I end up needing to up-cast MyBase to MyExtendedBase, which is illegal
in C#. I need my data layer to be able to accept and populate a
MyBaseCollectio n (with it possibly being a sub class of a
MyExtendedBaseC ollection) with MyBase objects (with them possibly being sub
classes of MyExtendedBase) , and then when the collection is returned, the
items in the collection are of the appropriate type (depending on the type
of collection passed in).

I have read about different design patterns (namely Decorator and
Composite), but am not sure if they apply to my situation, and if so, how to
implement them accordingly.

Again, I may be doing something totally illogical, so I'm open to any
suggestions you may have. Also, if I have not provided enough info, let me
know and I will follow up.

Thanks in advance.

Jerad
Mar 15 '06 #1
14 2581
I think your're pretty close. If you have a base class, then you should
have no problem passing MyExtendedBaseC ollection as a MyBaseCollectio n
object. This is the power of polymorphism.

A couple of your statements:
need my data layer to be able to accept and populate a
MyBaseCollectio n (with it possibly being a sub class of a
MyExtendedBaseC ollection) with MyBase objects (with them possibly being sub
classes of MyExtendedBase) ,


MyExtendedBase and MyExtendedBaseC ollection are sub classes of MyBase
and MyBaseCollectio n.

When you say a "subclass" it means that it inherits from a base class
or abstract class. I think you have the terminology backwards.

If you are trying to cast MyBase to MyExtendedBase, this is not going
to work. When you need to pass around a specialized type of class, but
dont want to code additional methods (apart from special functionality)
then you cast your dervied or subclasses (MyExtendedBase ) to type
MyBase, you can then pass it around as normal, any methods that are in
the base class that you override in the subclass, can be called as
normal because both the base class and sub class have definitions for
those methods.

Another way to accomplish this would be to use interfaces.

As far as the design patterns, this is something I am still learning as
well, I have found that if you dont understand the design pattern
completely, then dont use it at all. because chances are is that you
will miuse the pattern, and create more headaches then solutions.

hope my comments help!

Mar 15 '06 #2
Jerad Rose wrote:
do, I end up needing to up-cast MyBase to MyExtendedBase, which is illegal
That's a down-cast. It's "legal" (staticly valid), but if the actual
object instance casted is not an instance of MyExtendedBase the cast
will fail and throw an exception.
Again, I may be doing something totally illogical, so I'm open to any
suggestions you may have. Also, if I have not provided enough info, let me
know and I will follow up.


Let the data-layer, that should be generic in the types, accept the
data-structure to fill items into as an argument. If your data layer
needs to construct "unknown" type objects from data you can have a look
at the factory-pattern. The data-layer can accept, as a parameter, a
factory that is given the data to parse and create an object from that.

BTW: Are you in C#1 or 2?

Decorator and composite are completely unrelated to your problem.

--
Helge Jensen
mailto:he****** ****@slog.dk
sip:he********* *@slog.dk
-=> Sebastian cover-music: http://ungdomshus.nu <=-
Mar 15 '06 #3
Bob
Hi Jerad,
You only need one collection. The one for the base class.
When you're pulling in data from the database test the attribute(s) that
mark the difference between Mybase and MyExtendedBase before instantiating
the object that you are going to add to the collection.
bool MyDatabaseGetRo utine(ref collection col)
{
SQlDataCommand etc setup.
MyBase b;
While MyDatareader.re ad
{
If(MyDataReader .GetString(say5 ) == dbNull) //Instantiate a MyBase
b=new MyBase();
else // Instantiate a MyBaseExtended
b= new MyBaseExtended( );
// Now fill the common (MyBase) properties
b.Common1 = MyDataRead.GetS tring(0);
b.Common2 = MyDataRead.GetS tring(1);
Test again for type.
if (b.GetType().To String()=="MyBa seExtended")

{

// Fill the extended properties

}

col.add(b); Adding to collection regardless of Instantiation.

When you come to use the collection iterate across it with a base type
variable

bool LetsUnpackIt(co llection col)

foreach (mybase b in col)

{

if (b.gettype().To String()=="MyBa se")

//Do the mybase things

else

// Do the myBaseExtended things

HTH

Bob

"Jerad Rose" <no@spam.com> wrote in message
news:ea******** ******@TK2MSFTN GP09.phx.gbl...
I'm relatively new to C# and polymorphism, so what I'm trying to accomplish may not be possible, or there may be a totally different approach that I
should be taking.

I have a base class (MyBase) and a collection of MyBase objects
(MyBaseCollecti on). Now, I also have an extension to MyBase (MyExtendedBase : MyBase) that has additional properties. And lastly, I have a collection
of MyExtendedBase objects(MyExten dedBaseCollecti on : MyBaseCollectio n).

I have a data layer that has a method (GetMyBaseColle ction) that retrieves
records from the database, and populates a MyBaseCollectio n with these
records. However, there are cases where I need to use this method to
populate a MyExtendedBaseC ollection. But here's the catch -- I want my data layer to be unaware (and independent) of MyExtendedBase and
MyExtendedBaseC ollection.

I have tried several different ways to accomplish this, but no matter what I do, I end up needing to up-cast MyBase to MyExtendedBase, which is illegal
in C#. I need my data layer to be able to accept and populate a
MyBaseCollectio n (with it possibly being a sub class of a
MyExtendedBaseC ollection) with MyBase objects (with them possibly being sub classes of MyExtendedBase) , and then when the collection is returned, the
items in the collection are of the appropriate type (depending on the type
of collection passed in).

I have read about different design patterns (namely Decorator and
Composite), but am not sure if they apply to my situation, and if so, how to implement them accordingly.

Again, I may be doing something totally illogical, so I'm open to any
suggestions you may have. Also, if I have not provided enough info, let me know and I will follow up.

Thanks in advance.

Jerad

Mar 15 '06 #4
Thanks for the responses, guys.

To clarify on a few comments:

dkode wrote:
When you say a "subclass" it means that it inherits from a base class or abstract class. I think you have the terminology backwards.
Yeah, I guess I was thinking the "subclass" would be the more generic one
and have fewer members, sort of like a subset. Thanks for the
clarification.

dkode wrote:
I have found that if you dont understand the design pattern completely, then dont use it at all.
I tend to agree with you there, which was why I wouldn't have used them
unless somebody could have helped me understand them.

Helge Jensen wrote:
That's a down-cast. It's "legal" (staticly valid), but if the actual object instance casted is not an instance of MyExtendedBase the cast will fail and throw an exception.
Yeah, that's what I meant (see example below). But I did get the
up-/down-cast confused. But I think I've seen other people posting this
backwards as well.

Helge Jensen wrote:
The data-layer can accept, as a parameter, a
factory that is given the data to parse and create an object from that.
It seems this is the recommended way to go. And I had thought about going
this route originally, but the thing I don't like about using a factory is
that my data layer is dependent on this factory, which it turn is dependent
on my extended class -- which I was trying to avoid. However, I understand
this may be my only option.

Helge Jensen wrote:
BTW: Are you in C#1 or 2?
1.1

Bob wrote:
You only need one collection. The one for the base class.
Theoretically true, but I want my collections to be type-safe, so that
casting isn't required to access the extended members. However, if doing
this would remove the dependence of my data layer on my extended class, I
would go this route.
When you're pulling in data from the database test the attribute(s) that mark the difference between Mybase and MyExtendedBase before instantiating the object that you are going to add to the collection.


This is similar to the factory concept, and requires the same dependency of
my data layer on my extended object/properties. The data layer will not
need access to any of the extended properties, so I would prefer to not
require this dependency. But again, I may not have that option.

Repeating what I said in my original post, here is my setup:

MyBase

MyBaseCollectio n

MyExtendedBase : MyBase

MyExtendedBaseC ollection : MyBaseCollectio n

I can pass an instance of MyExtendedBaseC ollection to the data layer, caste
as MyBaseCollectio n. But when my data layer creates new MyBase objects and
adds them to the collection, there's no way I can down-cast them to
MyExtendedBase when I return from the data layer. I would think there would
be a way to have a base collection get populated with base objects, without
introducing the dependency of the underlying method on the extended
class/collection. It seems this would be a common need, but it sounds like
my options aren't as elegant as "best practices" encourage.

Dkode, you mentioned interfaces. Would the use of interfaces help
accomplish my goals?

Thanks again.

Jerad


Mar 15 '06 #5
If you want "type safety" (more likely you want to avoid the upcast
here) then you should consider a move to 2.0 and generics. You can do
something similar to this, I've done it in my own data
objects/collections

Something like:
MyBaseObj{ }
MyBaseCollectio n<T> : ICollection<T> where T : MyBaseObj
{
public T this[int index]
{
get
{
...
}
}

...
}

Then MyDerivedObj :MyBaseObj for your derived record obj
and MyDerivedCollec tion : MyBaseCollectio n<MyDerivedObj > for your
derived collection of derived record objects

Mar 16 '06 #6
Thats interesting how you accomplish this with generics. I need to read
up more on generics. All I have used them for is for a List collection
within another class. What does using the <T> accomplish? You don't
have to specify the type?

Mar 16 '06 #7
dkode wrote:
Thats interesting how you accomplish this with generics. I need to read
up more on generics. All I have used them for is for a List collection
within another class. What does using the <T> accomplish? You don't
have to specify the type?


You don't specify the type when writing the generic type; you specify
it when you *use* the type.

It's well worth reading up on generics - it's a massive topic though!

Jon

Mar 16 '06 #8
For those interested, I am posting below what ended up being the ultimate
solution I came to. This accomplishes both of my goals:

1) Type safety
2) Independence of data layer on extended classes

Your feedback is welcomed and appreciated.

Thanks.
Jerad

//Polymorphic Collections Example

public class MyBaseClass
{
//base member implementation
}

public class MyBaseCollectio n : ICollection
{
protected ArrayList _innerList;

public MyBaseClass this[int index]
{
get { return (MyBaseClass)_i nnerList[index]; }
}

public virtual MyBaseClass AddNewItem()
{
MyBaseClass newBaseItem = new MyBaseClass();
_innerList.Add( newBaseItem);
return newBaseItem;
}

//standard collection member implementation
}

public class MyExtendedClass : MyBaseClass
{
public string MyExtendedPrope rty
{
//get/set implementation
}
}

public class MyExtendedColle ction : MyBaseCollectio n
{
public new MyExtendedClass this[int index]
{
get { return (MyExtendedClas s)base._innerLi st[index]; }
}

public override MyBaseClass AddNewItem()
{
MyExtendedClass newExtendedItem = new MyExtendedClass ();
_innerList.Add( newExtendedItem );
return newExtendedItem ;
}
}

public class MyDataLayer
{
public void GetRecords(MyBa seCollection myBaseCol)
{
//database implementation

while(dr.Read() )
{
//This is critical -- using the collection's AddNewItem
//to instantiate the object will ensure the proper type
//is being instantiated. If the collection is an
//instance of MyExtendedColle ction, it will create and
//add an instance of MyExtendedClass to the collection.
//Otherwise, it will add an instance of MyBaseClass.

MyBaseClass myBase = myBaseCol.AddNe wItem();

//set myBase's base properties
}
}
}

public class TestClient
{
public void Main()
{
MyDateLayer myDL = new MyDataLayer();

//This will pass an instance of a base collection to the data layer
MyBaseCollectio n myBaseCol = new MyBaseCollectio n();
myDL.GetRecords (myBaseCol);
myBaseCol[0].MyExtededPrope rty = "Not legal";

//This will pass an instance of an extended collection to the data
layer
MyExtendedColle ction myExtCol = new MyExtendedColle ction();
myDL.GetRecords (myExtCol);
myExtCol[0].MyExtededPrope rty = "Legal";
}
}
Mar 16 '06 #9
I have a quick question about your implementation.

Doesn't this violate n-tier design because the datalayer has knowledge
of the business layer objects? I thought the data layer was only
supposed to return records (DataReader) in this instance, or is all of
this code in your data layer?
From other NG postings, I've had people tell me that the Data Layer has

NO knowledge of business layer objects, doing so violates proper N-Tier
design and tighly couples your business layer with your data layer.

Mar 16 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2572
by: The Directive | last post by:
I can't understand why in this folling example the message "Base.Draw()" is printed. Shouldn't "Derive.Draw" be printed because of polymorphism? How can I rewrite this example using a vector to achieve polymorphism. Help!!! I'm very confused. //Base class. class Base { public: Base()
12
7043
by: Steve Jorgensen | last post by:
The classing Visual Basic and VBA support for polymorphism, let's face it, is a bit on the weak side, and built-in support for inheritance is non-existent. This little essay is about some patterns I've ended up using successfully for certain kinds of inheritance and polymorphism, and some that have not worked out so well. Let's start with obvious things that turn out not to work well: 1. Use interface classes and "Implements" for...
2
2872
by: Marc | last post by:
Given a class 'Invoice' with a property 'public IMyColl<IInvoiceLine> InvoiceLines' where 'IMyColl<T> : IList<T>' i would like to detect by reflection that 'InvoiceLines' is a 'System.Collection.Generic.IList'. When performing something like: 'if (typeof(IList<>).IsAssignableFrom(propertyInfo.Type))' where 'propertyInfo' obviously refers to the 'InvoiceLines', the result is always 'false' because indeed 'IList<object>' and...
15
3036
by: rwf_20 | last post by:
I just wanted to throw this up here in case anyone smarter than me has a suggestion/workaround: Problem: I have a classic producer/consumer system which accepts 'commands' from a socket and 'executes' them. Obviously, each different command (there are ~20 currently) has its own needed functionality. The dream goal here would be to remove all knowledge of the nature of the command at runtime. That is, I don't want ANY switch/cases...
4
8179
by: nhmark64 | last post by:
Hi, Does System.Collections.Generic.Queue not have a Synchronized method because it is already in effect synchronized, or is the Synchronized functionality missing from System.Collections.Generic.Queue? Putting it another way can I safely replace a System.Collections.Queue.Synchronized(myUnSynchronizedQueue) with a System.Collections.Generic.Queue while porting a working 2003 project? Thanks,
13
14609
by: Krivenok Dmitry | last post by:
Hello all! Perhaps the most important feature of dynamic polymorphism is ability to handle heterogeneous collections of objects. ("C++ Templates: The Complete Guide" by David Vandevoorde and Nicolai M. Josuttis. Chapter 14.) How to implement analogue of this technique via static polymorphism? Perhaps there is special design pattern for this purpose...
9
1682
by: James Crosswell | last post by:
I'm not sure if I'm going about this the right way - it may be that Generics might be able to help me out here... but here goes: I have three classes as follows class BaseEdit class WidgetEdit: BaseEdit class FooEdit: BaseEdit These are all acutally Windows Forms and BaseEdit is an abstract class (and so never gets instantiated). I'd like to define a method in
3
1507
by: dippykdog | last post by:
I have an IRange interface defined as... Public Interface IRange Property Min() As Object Property Max() As Object End Interface ....and I want to implement that in different kinds of range objects like IntegerRange, StringRange, WeightRange, CurrencyRange, etc. But I can't implement the interface using more specific types like this Public Class IntegerRange
1
1603
by: mattmao | last post by:
I am brand new to C#.NET so here is my trial on this lab exercise: using System; using System.Collections.Generic; using System.Text; using System.Collections; namespace lab02exec { public class Program
0
8421
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8844
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8742
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8518
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8621
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7354
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6177
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
2
1971
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1734
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.