471,075 Members | 762 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

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

Help with class design

I come from a Delphi background, and am currently trying to port or convert
some of our Delphi classes to C#. I've got a good handle on basic class
design, but am a bit lost with some of the more advanced things I need to
do, and was hoping somebody could point me to an online resource that can
help me better understand what I need to do.

For example, one of the classes is a Shipment class. A Shipment can have
any number of Packages, so I have designed a Shipment Class and a Package
class. I should be able to retrieve any of the packages by it's index or I
should be able to use a single package as a property. For example (these
examples are not working code, merely pseudo-code to demonstrate what I
need):

oShip = new Shipment();
oShip.AddPackage(sPackageID, dPackageWeight);
oShip.AddPackage(sDifferentPackageID, dPackageWeight);

// access the first package object in the shipment
MessageBox.Show(oShip.Packages[0].PackageID);

// loop though all packages
foreach(Package oPack in oShipment)
{
MessageBox.Show(oPack.PackageID);
}

Either a basic template that shows how I need to design my class or a good
online resource would be greatly appreciated!

TIA!
Nov 17 '05 #1
6 1343
J... The Shipment class probably should not expose its internal data
like that. In other words, I would not allow an external caller to
access the Package collection in the Shipment directly. I would add a
level of indirection here, Properties for instance. Internally, the
Shipment class can store the Packages in a private array or in a
private, type safe collection derived from collection base. Externally,
the Shipment can provide get accessors (by index and/or key) or return a
read only collection or a copy of the internal array so the caller has
access to the individual packages but not to the private internal
collection in the shipment object. You can then add set accessors (Add,
Remove) that validate any attempt to modify the contents of the internal
collection.

Regards,
Jeff
// loop though all packages
foreach(Package oPack in oShipment)
{
MessageBox.Show(oPack.PackageID);
}
*** Sent via Developersdex http://www.developersdex.com ***
Nov 17 '05 #2
"JSheble" <js************@logicor.com> a écrit dans le message de news:
#K*************@TK2MSFTNGP15.phx.gbl...
I come from a Delphi background, and am currently trying to port or convert some of our Delphi classes to C#. I've got a good handle on basic class
design, but am a bit lost with some of the more advanced things I need to
do, and was hoping somebody could point me to an online resource that can
help me better understand what I need to do.
There really is no difference in how you would design classes in C# as
opposed to Delphi. If you got the design right in Delphi, then it should be
fine in C# :-)
For example, one of the classes is a Shipment class. A Shipment can have
any number of Packages, so I have designed a Shipment Class and a Package
class. I should be able to retrieve any of the packages by it's index or I should be able to use a single package as a property. For example (these
examples are not working code, merely pseudo-code to demonstrate what I
need):
You need to start off by asking yourself whether a Package can exist outside
of a Shipment e.g. can a Package be stored in a Warehouse or transported in
a DeliveryVehicle.

If a Package can exist outside of a Shipment then the relationship between
them is one of Aggregation and can be expressed thus :

class Package
{
...
}

class PackageList
{
void Add(Package item)...
void Remove(Package item)...
Package this[int idx]...
...
}

class Shipment
{
PackageList Packages
{
get {...}
set {...}
}
}

But if the Packages cannot exist outside of a Shipment then the relationship
is one of Composition and should be expressed thus :

class Package
{
...
}

class Shipment
{
Package AddPackage()...
void RemovePackage(Package item)...
int PackageCount
{
get {...}
}...
PackageEnumerator GetPackageEnumerator()...
...
}

The essential difference is that the Composition relationship should not
allow adding or otherwise manipulating Packages without going through
methods of the Shipment.
oShip = new Shipment();
oShip.AddPackage(sPackageID, dPackageWeight);
oShip.AddPackage(sDifferentPackageID, dPackageWeight);
PAckageWeight should be a property of the Package class and you should not
need to pass such details to the Add method of the Shipment class. Assuming
you are using Composition, you should retrieve a new instance of the Package
class from the Shipment and set properties like Weight, etc on that
instance. I suspect though that you should be using Aggregation and
therefore you should create an instance of Package, set the properties
either in the constructor or otherwise, and then add the instance to the
Shipment.
// loop though all packages
foreach(Package oPack in oShipment)
{
MessageBox.Show(oPack.PackageID);
}


I am not sure whether you really should make the Shipment 'enumerable', that
implies it not really much more than a list ??

Joanna

--
Joanna Carter (TeamB)
Consultant Software Engineer
Nov 17 '05 #3
Ok, so assuming a package cannot exist outside of a shipment, I would be
using the Composition type. In reality, a package could exist outside of a
shipment in the real world, but for this object model, it makes no sense to
have a package without a shipment.

But this line of pseudo-code you added:

PackageEnumerator GetPackageEnumerator()...

makes no sense to me. I'm assuming I will have to create a
PackageEnumerator type? Which should have or do what exactly?

I don't suppose you'd have a small example class showing or demonstrating
this, would you? Once I see and digest an example, hopefully I'd be able to
simulate it for my specific needs.
PAckageWeight should be a property of the Package class and you should not
need to pass such details to the Add method of the Shipment class.
Assuming
you are using Composition, you should retrieve a new instance of the
Package
class from the Shipment and set properties like Weight, etc on that
instance.
Actually, a package cannot exist without a weight, which is why I'm adding
it to the Addpackage method. A package must have a package ID and a weight.
If not, there's no sense in adding a package. I think leaving the weight as
a parameter is a feasible solution.

"Joanna Carter (TeamB)" <jo*****@nospamforme.com> wrote in message
news:%2****************@tk2msftngp13.phx.gbl... "JSheble" <js************@logicor.com> a écrit dans le message de news:
#K*************@TK2MSFTNGP15.phx.gbl...
I come from a Delphi background, and am currently trying to port or

convert
some of our Delphi classes to C#. I've got a good handle on basic class
design, but am a bit lost with some of the more advanced things I need to
do, and was hoping somebody could point me to an online resource that can
help me better understand what I need to do.


There really is no difference in how you would design classes in C# as
opposed to Delphi. If you got the design right in Delphi, then it should
be
fine in C# :-)
For example, one of the classes is a Shipment class. A Shipment can have
any number of Packages, so I have designed a Shipment Class and a Package
class. I should be able to retrieve any of the packages by it's index or

I
should be able to use a single package as a property. For example (these
examples are not working code, merely pseudo-code to demonstrate what I
need):


You need to start off by asking yourself whether a Package can exist
outside
of a Shipment e.g. can a Package be stored in a Warehouse or transported
in
a DeliveryVehicle.

If a Package can exist outside of a Shipment then the relationship between
them is one of Aggregation and can be expressed thus :

class Package
{
...
}

class PackageList
{
void Add(Package item)...
void Remove(Package item)...
Package this[int idx]...
...
}

class Shipment
{
PackageList Packages
{
get {...}
set {...}
}
}

But if the Packages cannot exist outside of a Shipment then the
relationship
is one of Composition and should be expressed thus :

class Package
{
...
}

class Shipment
{
Package AddPackage()...
void RemovePackage(Package item)...
int PackageCount
{
get {...}
}...
PackageEnumerator GetPackageEnumerator()...
...
}

The essential difference is that the Composition relationship should not
allow adding or otherwise manipulating Packages without going through
methods of the Shipment.
oShip = new Shipment();
oShip.AddPackage(sPackageID, dPackageWeight);
oShip.AddPackage(sDifferentPackageID, dPackageWeight);


PAckageWeight should be a property of the Package class and you should not
need to pass such details to the Add method of the Shipment class.
Assuming
you are using Composition, you should retrieve a new instance of the
Package
class from the Shipment and set properties like Weight, etc on that
instance. I suspect though that you should be using Aggregation and
therefore you should create an instance of Package, set the properties
either in the constructor or otherwise, and then add the instance to the
Shipment.
// loop though all packages
foreach(Package oPack in oShipment)
{
MessageBox.Show(oPack.PackageID);
}


I am not sure whether you really should make the Shipment 'enumerable',
that
implies it not really much more than a list ??

Joanna

--
Joanna Carter (TeamB)
Consultant Software Engineer

Nov 17 '05 #4
The package collection has to be available through the Shipment object.
Accessing it via oSHipment.Packages[iPkg].SomePackageProperty is the
desirable method for accessing individual packages or through an enumerator.

"Jeff Louie" <je********@yahoo.com> wrote in message
news:OP**************@TK2MSFTNGP12.phx.gbl...
J... The Shipment class probably should not expose its internal data
like that. In other words, I would not allow an external caller to
access the Package collection in the Shipment directly. I would add a
level of indirection here, Properties for instance. Internally, the
Shipment class can store the Packages in a private array or in a
private, type safe collection derived from collection base. Externally,
the Shipment can provide get accessors (by index and/or key) or return a
read only collection or a copy of the internal array so the caller has
access to the individual packages but not to the private internal
collection in the shipment object. You can then add set accessors (Add,
Remove) that validate any attempt to modify the contents of the internal
collection.

Regards,
Jeff
// loop though all packages
foreach(Package oPack in oShipment)
{
MessageBox.Show(oPack.PackageID);
}
*** Sent via Developersdex http://www.developersdex.com ***

Nov 17 '05 #5
I see. My bad.
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
Package p1= new Package(21);
Package p2= new Package(35);
Shipment s1= new Shipment();
s1.Add(p1);
s1.Add(p2);
for (int i=0; i<s1.Count;i++)
{
System.Console.Write(s1.GetPackage(i).ID+":");
System.Console.WriteLine(s1.GetPackage(i).Weight);
}
foreach(Package p in s1)
{
System.Console.Write(p.ID+":");
System.Console.WriteLine(p.Weight);
}
System.Console.ReadLine();
}

public class Package : IPackage
{
// static stuff
private static int uniqueID= 0;
private static int GetUniqueID()
{
lock(typeof(Package))
{
return uniqueID++; // returns zero at start
}
}

private int weight= 0;
private int id;

public Package(int weight)
{
this.id= Package.GetUniqueID();
if (weight > 0)
{
this.weight= weight;
}
}
#region IPackage Members
...
Regards,
Jeff

*** Sent via Developersdex http://www.developersdex.com ***
Nov 17 '05 #6
"JSheble" <js************@logicor.com> a écrit dans le message de news:
er**************@TK2MSFTNGP10.phx.gbl...
Ok, so assuming a package cannot exist outside of a shipment, I would be
using the Composition type. In reality, a package could exist outside of a shipment in the real world, but for this object model, it makes no sense to have a package without a shipment.
I still have my doubts about using Composition, but for the sake of example,
let's continue...
But this line of pseudo-code you added:

PackageEnumerator GetPackageEnumerator()...

makes no sense to me. I'm assuming I will have to create a
PackageEnumerator type? Which should have or do what exactly?
This just needs to implement IEnumerator; two methods : Reset(), MoveNext()
and one property : Current.
PAckageWeight should be a property of the Package class and you should not need to pass such details to the Add method of the Shipment class.
Assuming
you are using Composition, you should retrieve a new instance of the
Package
class from the Shipment and set properties like Weight, etc on that
instance.


Actually, a package cannot exist without a weight, which is why I'm adding
it to the Addpackage method. A package must have a package ID and a

weight. If not, there's no sense in adding a package. I think leaving the weight as a parameter is a feasible solution.


Assuming you are using Composition, then your method that takes two
parameters would be sensible.

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker
Nov 17 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

9 posts views Thread by Sacha | last post: by
8 posts views Thread by Martin Horn | last post: by
4 posts views Thread by Brian | last post: by
2 posts views Thread by Carlo, MCP | last post: by
1 post views Thread by stalinmaddy | last post: by
5 posts views Thread by aaragon | last post: by
4 posts views Thread by Andrew Taylor | last post: by
reply views Thread by leo001 | 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.