Using generics in the Composite Design Pattern to avoid Boxing

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Basically I'd like to implement the composite design pattern with leaves that
are either of reference or value types, but even using generics I can't seem
to avoid boxing (using ArrayList or Object)

Is this even possible, or is the composite pattern doomed to use the
System.Object type forever?

I have tried using interfaces with generics, but I always stumble on the
Value property (when trying to return the value of a particular node)

I'd like to record the children in a
System.Collections.Generic.Dictionary<string, Node>

I can't create any Node class that fills in the blank, no matter how I try.
I always run into having to have two differnt kinds of Value properties for
the Node item -- one for refernce types and one for value types, and if I
have to differentiate, then I lose the benefit of the pattern, and if I
don't... all I can see as a way out is Boxing...


Am I trying to do something that's impossible here?
 
dave.dolan said:
Basically I'd like to implement the composite design pattern with
leaves that are either of reference or value types, but even using
generics I can't seem to avoid boxing (using ArrayList or Object)

Is this even possible, or is the composite pattern doomed to use the
System.Object type forever?

Boxing only occurs with value types when an instance of these is
referenced by an object reference, e.g. in an arraylist. When you store
a reference type (everything that's not a valuetype) in an arraylist
for example, boxing doesn't occur, as boxing isn't necessary: the value
stored is already an object.

My understanding of the composite pattern is that I don't see it as a
useful pattern for valuetypes: valuetypes are often small structs which
contain very few behavior and data. If you use bigger objects as
valuetypes, I think it's better to move to a class type instead. Could
you give an example of a typical value type you're using which needs to
be a valuetype according to you?

FB



--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
Dave,

If you want Node to be from an undependent Type, than the only Type that can
be used for that is Object, because it is the base of everything. Which
means that you are forever boxing.

(Your object holds the address it is referencing which can be too a value or
an other object) Although the last is seldom seen as boxing.

But boxing is not that bad as it is often given as idea in Net. Somebody
very active in this newsgroup did not believe me about that and does believe
me now more and more after a day testing.

:-)

Cor
 
"dave.dolan" <[email protected]> a écrit dans le message
de news: (e-mail address removed)...

| Basically I'd like to implement the composite design pattern with leaves
that
| are either of reference or value types, but even using generics I can't
seem
| to avoid boxing (using ArrayList or Object)
|
| Is this even possible, or is the composite pattern doomed to use the
| System.Object type forever?
|
| I have tried using interfaces with generics, but I always stumble on the
| Value property (when trying to return the value of a particular node)
|
| I'd like to record the children in a
| System.Collections.Generic.Dictionary<string, Node>
|
| I can't create any Node class that fills in the blank, no matter how I
try.
| I always run into having to have two differnt kinds of Value properties
for
| the Node item -- one for refernce types and one for value types, and if I
| have to differentiate, then I lose the benefit of the pattern, and if I
| don't... all I can see as a way out is Boxing...
|
|
| Am I trying to do something that's impossible here?

????????????????

The normal composite pattern can be achieved like this :

public class Composite<itemT> where itemT : new()
{
private List<itemT> items = new List<itemT>();

public itemT Add()
{
itemT newItem = new itemT();
items.Add(newItem);
return newItem;
}

public itemT this[int index]
{
return items[index];
}
...
}

Now, if you use this as expected :

{
Composite<int> test = new Composite<int>();

int item = test.Add();

item = 123;

Console WriteLine(test[0]);
}

Because you are using a value type, the value you assign to item is not
applied to test[0] because item is a copy of the item held in the list, as
with all value types.

Because of this behaviour of copy on assignment semantics, I would say that,
apart from Frans' assertion that you would not normally *want* to use value
types in a composite, you *cannot* use value types in the Composite pattern.

Like Frans, I would also like to know why you would want to use value types
?

Joanna
 
I don't want to use value types themselves as nodes, but I'd like to use
'nodes' representative of a value type.

Here's what I'm getting at:

I want to use a structure that can be referred to by an interface to be the
node. I cannot construct an interface that allows me to retreive and set the
values of the nodes without boxing.

For example, when I'm going to remote a structure that mirrors the data
values of an object as a tree of values (but doesn't use XML to do this) It's
definitely within reason to expect that I can pass both numeric and string
types as the node values... The Node item itself of course need not be a
value type, but the value it represents may be. The problem is that I can't
create a node INTERFACE that would represent a Node that has a property that
allows me to retreive and set this value without using the type Object. Cor
Ligthert seems to understand what I'm getting at, judging by the response, so
I think I'll go with that idea and box. I can at least avoid any GetType()
operations by defining my own substitutes for typecodes with an enumeration
type. (I've seen that done by others and it seems to be on the order of 10
times faster than using the system.object.GetType()).

You guys are right though, the node itself shouldn't and wouldn't be a value
type, I was referring to the value encased in the node, and perhaps I wasn't
clear enough.

Thank you everyone for your insightful responses!

However
Joanna Carter said:
"dave.dolan" <[email protected]> a écrit dans le message
de news: (e-mail address removed)...

| Basically I'd like to implement the composite design pattern with leaves
that
| are either of reference or value types, but even using generics I can't
seem
| to avoid boxing (using ArrayList or Object)
|
| Is this even possible, or is the composite pattern doomed to use the
| System.Object type forever?
|
| I have tried using interfaces with generics, but I always stumble on the
| Value property (when trying to return the value of a particular node)
|
| I'd like to record the children in a
| System.Collections.Generic.Dictionary<string, Node>
|
| I can't create any Node class that fills in the blank, no matter how I
try.
| I always run into having to have two differnt kinds of Value properties
for
| the Node item -- one for refernce types and one for value types, and if I
| have to differentiate, then I lose the benefit of the pattern, and if I
| don't... all I can see as a way out is Boxing...
|
|
| Am I trying to do something that's impossible here?

????????????????

The normal composite pattern can be achieved like this :

public class Composite<itemT> where itemT : new()
{
private List<itemT> items = new List<itemT>();

public itemT Add()
{
itemT newItem = new itemT();
items.Add(newItem);
return newItem;
}

public itemT this[int index]
{
return items[index];
}
...
}

Now, if you use this as expected :

{
Composite<int> test = new Composite<int>();

int item = test.Add();

item = 123;

Console WriteLine(test[0]);
}

Because you are using a value type, the value you assign to item is not
applied to test[0] because item is a copy of the item held in the list, as
with all value types.

Because of this behaviour of copy on assignment semantics, I would say that,
apart from Frans' assertion that you would not normally *want* to use value
types in a composite, you *cannot* use value types in the Composite pattern.

Like Frans, I would also like to know why you would want to use value types
?

Joanna
 
"dave.dolan" <[email protected]> a écrit dans le message
de news: (e-mail address removed)...

| I want to use a structure that can be referred to by an interface to be
the
| node. I cannot construct an interface that allows me to retreive and set
the
| values of the nodes without boxing.

Why would you need to box ?

public interface INode
{
...
}

public interface INode<nodeT> : INode
{
nodeT Value { get; set; }
}

Or you can do this :

public interface INode
{
nodeT GetValue<nodeT>();
void SetValue<nodeT>(nodeT value);
}

Then you can create a List<INode>, or whatever, to hold the nodes.

Having to test for node type whilst reading and writing from/to nodes can be
eliminatedby adding the Visitor pattern to the class that implements the
node interface.

Does that help or confuse ? :-)

Joanna
 
Well, I still need to read the value of the node, as in the type contained
within the node, not just the node itself. If the node represents an
integer, I need to call Value on the node and get an integer, if it
represents an array of strings, I need to call Value on the node and return
an array of strings. According to the reading I've done this morning, and
from what people are saying here there isn't a way to generically represent
both without using the type System.Object.

So the node will have to use an interface like this:

interface INode {
Object Value { get; set; }
int CountChildren();
List<INode> Children {get;}
}

What you're suggesting is for the composite pattern itself, which would be
correct, but what I'm looking for is the value of the objects being
composited. (Not a reference to the wrapping Node object.) I'm pretty
certain now that it needs to box.
 
"dave.dolan" <[email protected]> a écrit dans le message
de news: (e-mail address removed)...

| Well, I still need to read the value of the node, as in the type contained
| within the node, not just the node itself. If the node represents an
| integer, I need to call Value on the node and get an integer, if it
| represents an array of strings, I need to call Value on the node and
return
| an array of strings. According to the reading I've done this morning, and
| from what people are saying here there isn't a way to generically
represent
| both without using the type System.Object.
|
| So the node will have to use an interface like this:
|
| interface INode {
| Object Value { get; set; }
| int CountChildren();
| List<INode> Children {get;}
| }

So why not separate out the value from the rest of the node behaviour ?

Then there is no boxing required :

interface INode
{
int CountChildren();
List<INode> Children {get;}
}

interface INode<nodeT> : INode
{
nodeT Value { get; set; }
}

class Node<T> : INode<T>
{
private List<INode> children = new List<INode>();

private nodeT value;

int INode.CountChildren()
{
return children.Count;
}

List<INode> INode.Children
{
get { return children; }
}

nodeT INode<nodeT>.Value
{
get { return value; }
set { this.value = value; }
}
}

Used like this :

{
INode baseNode = new INode<int>();
baseNode.Value = 123;

INode newNode = new INode<string[]>();
newNode.Value = new string[] { "hello", "world" }

baseNode.Children.Add(newNode);

// etc...
}

| What you're suggesting is for the composite pattern itself, which would be
| correct, but what I'm looking for is the value of the objects being
| composited. (Not a reference to the wrapping Node object.) I'm pretty
| certain now that it needs to box.

Go on, convince me why :-))

Joanna
 
In your example you're using INode and INode<T> interchangably, which they
aren't..

When you declare something as type INode, there is no knowledge of the fact
that INode<T> has a Value property.

This is the same brick wall I've been hitting that prompted me to ask this
question to begin with. It was kinda driving me nuts, and I think that you
can see what I mean now.

--dave
 
I think you meant to use Node instead of INode, but the same problem exists.

INode baseNode = new Node<int>();

When I go to say baseNode.Value = something, it won't know what I mean
because it doesn't have that propety.

I could cast it, but I'd have to know what to cast it to first... and since
it's a type parameter, I'm back at square one.

dave.dolan said:
In your example you're using INode and INode<T> interchangably, which they
aren't..

When you declare something as type INode, there is no knowledge of the fact
that INode<T> has a Value property.

This is the same brick wall I've been hitting that prompted me to ask this
question to begin with. It was kinda driving me nuts, and I think that you
can see what I mean now.

--dave
Joanna Carter said:
"dave.dolan" <[email protected]> a écrit dans le message
de news: (e-mail address removed)...

| Well, I still need to read the value of the node, as in the type contained
| within the node, not just the node itself. If the node represents an
| integer, I need to call Value on the node and get an integer, if it
| represents an array of strings, I need to call Value on the node and
return
| an array of strings. According to the reading I've done this morning, and
| from what people are saying here there isn't a way to generically
represent
| both without using the type System.Object.
|
| So the node will have to use an interface like this:
|
| interface INode {
| Object Value { get; set; }
| int CountChildren();
| List<INode> Children {get;}
| }

So why not separate out the value from the rest of the node behaviour ?

Then there is no boxing required :

interface INode
{
int CountChildren();
List<INode> Children {get;}
}

interface INode<nodeT> : INode
{
nodeT Value { get; set; }
}

class Node<T> : INode<T>
{
private List<INode> children = new List<INode>();

private nodeT value;

int INode.CountChildren()
{
return children.Count;
}

List<INode> INode.Children
{
get { return children; }
}

nodeT INode<nodeT>.Value
{
get { return value; }
set { this.value = value; }
}
}

Used like this :

{
INode baseNode = new INode<int>();
baseNode.Value = 123;

INode newNode = new INode<string[]>();
newNode.Value = new string[] { "hello", "world" }

baseNode.Children.Add(newNode);

// etc...
}

| What you're suggesting is for the composite pattern itself, which would be
| correct, but what I'm looking for is the value of the objects being
| composited. (Not a reference to the wrapping Node object.) I'm pretty
| certain now that it needs to box.

Go on, convince me why :-))

Joanna
 
"dave.dolan" <[email protected]> a écrit dans le message
de news: (e-mail address removed)...

| I think you meant to use Node instead of INode, but the same problem
exists.
|
| INode baseNode = new Node<int>();

Yes, sorry, Outlook Express doesn't have code insight :-)

| When I go to say baseNode.Value = something, it won't know what I mean
| because it doesn't have that propety.

If you are going to set the Value property of a node to an int, then you
know what type to cast the node to INode<int>; then you can set the property
in a typesafe manner without boxing.

| I could cast it, but I'd have to know what to cast it to first... and
since
| it's a type parameter, I'm back at square one.

If you are iterating through a tree and are unable to determine the type of
each node individually, then the answer is the Visitor design pattern which
takes away the need to know the type of each node.

Joanna
 
"dave.dolan" <[email protected]> a écrit dans le message
de news: (e-mail address removed)...

| In your example you're using INode and INode<T> interchangably, which they
| aren't..

If INode<T> derives from INode, then they are type compatible.

| When you declare something as type INode, there is no knowledge of the
fact
| that INode<T> has a Value property.

Correct, but that is wherfe the Visitor pattern can come in useful.

| This is the same brick wall I've been hitting that prompted me to ask this
| question to begin with. It was kinda driving me nuts, and I think that
you
| can see what I mean now.

Are you familiar with the Visitor pattern ?

Joanna
 
hey! thanks! visitor pattern did the trick. I wrote up a little demo. I'm
going to fix it up some more and blog it, but for now, the source is at
http://davedolan.com/CompositeTest.zip Probably should be called VisitorTest,
but I didn't rename the project after switching gears.

Thanks!
 
Ok I finally got out from behind the firewall and got the attachment. I see
what you mean about using the generics more. I can add the stuff about the
depth and ascent and descent to specific implementations, and don't really
need that in the pattern itself. I know you're not getting paid, and I'd
like to thank you very much for hitting me over the head until I realized
there's a better way to do this. I'm working on some really cool stuff with
an Associative database called Relavance, so if you ever hear of it again,
you can think back to when you helped this poor schlep break out of
GCC-style thinking ;)


--dave
 
"Dave Dolan" <[email protected]> a écrit dans le message de
%[email protected]...

| Ok I finally got out from behind the firewall and got the attachment. I
see
| what you mean about using the generics more. I can add the stuff about
the
| depth and ascent and descent to specific implementations, and don't really
| need that in the pattern itself. I know you're not getting paid, and I'd
| like to thank you very much for hitting me over the head until I realized
| there's a better way to do this. I'm working on some really cool stuff
with
| an Associative database called Relavance, so if you ever hear of it again,
| you can think back to when you helped this poor schlep break out of
| GCC-style thinking ;)

Heheh, one of the problems with all the standard explanations/examples of
generics is that they always seem to concentrate on demonstrating
lists/containers. Add to that the background of having to derive from
CollectionBase, or similar, to get a typed collection and it isn't
surprising that you ended up with the "wrapper" classes you did :-)

So far, my persistence, presentation and business frameworks make use of
over 50 of my own generic classes, interfaces and delegates, not to mention
all those from the FCL.

In some cases, I have cut the code used by up to 80% compared with the
Delphi typesafe, non-generic code I had.

:-)

Joanna
 
Back
Top