Generics and collections

This is a multi-part message in MIME format.

------=_NextPart_000_0006_01C89660.C1AA00F0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

I do not know if what I am trying to do is impossible, however since I =
cannot work out how to do it I thought I would post it here in the hope =
of some assistance.

Consider the following code ...

using System;

public class Parameter<T> {

private T value;

public Parameter() {
}

public Parameter(T value)
: this() {
this.value =3D value;
}

public T Value {
get { return this.value; }
set { this.value =3D value; }
}
}

public class BooleanParameter : Parameter<Boolean> {
}

public class ByteParameter : Parameter<Byte> {
}

public class WordParameter : Parameter<UInt16> {
}

As you can see, this is a simple example where I am creating generic =
types that will all expose a 'Value' property, but each of the 'Value' =
properties will have a different data type.

If I want to create collections for these types, again this is fairly =
basic ...

using System.Collections.ObjectModel;

public class BooleanParameterCollection : =
Collection<BooleanParameter> {
}

public class ByteParameterCollection : Collection<ByteParameter> {
}

public class WordParameterCollection : Collection<WordParameter> {
}

However, what I actually want is to create a collection of Parameter<?> =
objects; that is, a single typed collection that can contain =
BooleanParameter, ByteParameter or WordParameter objects intermingled =
with each other and then determine which of the objects I am working =
with at run time.

I have tried various combinations of interfaces and base classes, but =
all to no avail. Is this possible, if so, can anybody help me see the =
light?

Thanks in advance.

Martin.
------=_NextPart_000_0006_01C89660.C1AA00F0
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.6000.16608" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY>
<DIV><FONT face=3DArial size=3D2>I do not know if what I am trying to do =
is
impossible, however since I cannot work out how to do it I thought I =
would post
it here in the hope of some assistance.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Consider the following code =
....</FONT></DIV>
<DIV><FONT face=3DArial><FONT size=3D2><FONT face=3DArial
size=3D2></FONT></FONT></FONT> </DIV><FONT face=3DArial =
size=3D2><FONT size=3D1>
<DIV></FONT><FONT color=3D#0000ff>    using</FONT><FONT
size=3D1><FONT size=3D2> System;</FONT></DIV>
<DIV></FONT><FONT color=3D#0000ff></FONT> </DIV>
<DIV><FONT color=3D#0000ff>    public</FONT> <FONT
color=3D#0000ff>class</FONT> <FONT color=3D#2b91af>Parameter</FONT><FONT =

size=3D1><FONT size=3D2><T> {</FONT></DIV>
<DIV></FONT><FONT color=3D#0000ff></FONT> </DIV>
<DIV><FONT color=3D#0000ff>       
private</FONT><FONT size=3D1><FONT size=3D2> T value;</FONT></DIV>
<DIV></FONT><FONT color=3D#0000ff></FONT> </DIV>
<DIV><FONT color=3D#0000ff>       
public</FONT><FONT size=3D1><FONT size=3D2> Parameter() {</FONT></DIV>
<DIV><FONT size=3D2>        }</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV></FONT><FONT color=3D#0000ff>       
public</FONT><FONT size=3D1><FONT size=3D2> Parameter(T =
value)</FONT></DIV>
<DIV></FONT><FONT size=3D2>       
    : <FONT color=3D#0000ff>this</FONT>() {</FONT><FONT
size=3D1></DIV>
<DIV></FONT><FONT color=3D#0000ff>       
    this</FONT><FONT size=3D1><FONT size=3D2>.value =3D
value;</FONT></DIV>
<DIV><FONT size=3D2>        }</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV></FONT><FONT color=3D#0000ff>       
public</FONT><FONT size=3D1><FONT size=3D2> T Value {</FONT></DIV>
<DIV></FONT><FONT color=3D#0000ff>       
    get</FONT> { <FONT color=3D#0000ff>return</FONT> =
<FONT
color=3D#0000ff>this</FONT><FONT size=3D1><FONT size=3D2>.value; =
}</FONT></DIV>
<DIV></FONT><FONT color=3D#0000ff>       
    set</FONT> { <FONT color=3D#0000ff>this</FONT>.value =
=3D <FONT
color=3D#0000ff>value</FONT><FONT size=3D1><FONT size=3D2>; =
}</FONT></DIV>
<DIV><FONT size=3D2>        }</FONT></DIV>
<DIV><FONT size=3D2>    }</FONT></DIV>
<DIV></FONT><FONT color=3D#0000ff></FONT> </DIV>
<DIV><FONT color=3D#0000ff>    public</FONT> <FONT
color=3D#0000ff>class</FONT> <FONT =
color=3D#2b91af>BooleanParameter</FONT> : <FONT
color=3D#2b91af>Parameter</FONT><<FONT =
color=3D#2b91af>Boolean</FONT><FONT
size=3D1><FONT size=3D2>> {</FONT></DIV>
<DIV><FONT size=3D2>    }</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV></FONT><FONT color=3D#0000ff>    public</FONT> <FONT =

color=3D#0000ff>class</FONT> <FONT color=3D#2b91af>ByteParameter</FONT> =
: <FONT
color=3D#2b91af>Parameter</FONT><<FONT =
color=3D#2b91af>Byte</FONT><FONT
size=3D1><FONT size=3D2>> {</FONT></DIV>
<DIV><FONT size=3D2>    }</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV></FONT><FONT color=3D#0000ff>    public</FONT> <FONT =

color=3D#0000ff>class</FONT> <FONT color=3D#2b91af>WordParameter</FONT> =
: <FONT
color=3D#2b91af>Parameter</FONT><<FONT =
color=3D#2b91af>UInt16</FONT><FONT
size=3D1><FONT size=3D2>> {</FONT></DIV>
<DIV><FONT size=3D2>    }</FONT></DIV></FONT></FONT>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>As you can see, this is a simple =
example where I am
creating generic types that will all expose a 'Value' property, but each =
of the
'Value' properties will have a different data type.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>If I want to create collections for =
these types,
again this is fairly basic ...</FONT></DIV>
<DIV><FONT face=3DArial><FONT size=3D2><FONT face=3DArial
size=3D2></FONT></FONT></FONT> </DIV><FONT face=3DArial =
size=3D2><FONT size=3D1>
<DIV></FONT><FONT color=3D#0000ff>    using</FONT><FONT
size=3D1><FONT size=3D2> =
System.Collections.ObjectModel;</FONT></FONT></DIV>
<DIV><FONT size=3D1><FONT size=3D2></FONT> </DIV>
<DIV></FONT><FONT color=3D#0000ff>    public</FONT> <FONT =

color=3D#0000ff>class</FONT> <FONT =
color=3D#2b91af>BooleanParameterCollection</FONT>
: <FONT color=3D#2b91af>Collection</FONT><<FONT
color=3D#2b91af>BooleanParameter</FONT><FONT size=3D1><FONT =
size=3D2>>
{</FONT></DIV>
<DIV><FONT size=3D2>    }</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV></FONT><FONT color=3D#0000ff>    public</FONT> <FONT =

color=3D#0000ff>class</FONT> <FONT =
color=3D#2b91af>ByteParameterCollection</FONT> :
<FONT color=3D#2b91af>Collection</FONT><<FONT
color=3D#2b91af>ByteParameter</FONT><FONT size=3D1><FONT size=3D2>> =
{</FONT></DIV>
<DIV><FONT size=3D2>    }</FONT></DIV>
<DIV><FONT size=3D2></FONT> </DIV>
<DIV></FONT><FONT color=3D#0000ff>    public</FONT> <FONT =

color=3D#0000ff>class</FONT> <FONT =
color=3D#2b91af>WordParameterCollection</FONT> :
<FONT color=3D#2b91af>Collection</FONT><<FONT
color=3D#2b91af>WordParameter</FONT><FONT size=3D1><FONT size=3D2>> =
{</FONT></DIV>
<DIV><FONT size=3D2>    }</FONT></DIV></FONT></FONT>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>However, what I actually want is to =
create a
collection of <FONT color=3D#2b91af>Parameter</FONT><FONT size=3D1><FONT =

size=3D2><?> objects; that is, a single typed collection that can
contain <FONT color=3D#2b91af>BooleanParameter</FONT>, <FONT
color=3D#2b91af>ByteParameter</FONT> or <FONT
color=3D#2b91af>WordParameter</FONT> objects intermingled with each =
other and then
determine which of the objects I am working with at run
time.</FONT></FONT></FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>I have tried various combinations of =
interfaces and
base classes, but all to no avail. Is this possible, if so, can anybody =
help me
see the light?</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Thanks in advance.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>Martin.</FONT></DIV></BODY></HTML>

------=_NextPart_000_0006_01C89660.C1AA00F0--
Martin Robins [ Fr, 04 April 2008 15:32 ] [ ID #1935329 ]

Re: Generics and collections

Well, you can use object - otherwise you need to use a layer of
abstraction, such as a pair of interfaces allowing both typed (generic)
and untyped access:

using System.Collections.Generic;
using System;
interface IValue
{
Type ValueType { get; }
object Value { get; set; }
}
interface IValue<T> : IValue
{
new T Value { get; set; }
}
class Parameter<T> : IValue<T>
{
public Type ValueType
{
get { return typeof(T); }
}
private T value;
public T Value
{
get { return this.value; }
set { this.value = value; }
}
object IValue.Value
{
get { return Value; }
set { Value = (T)value; }
}
public Parameter() { }
public Parameter(T value) { Value = value; }
}


static class Program
{
static void Main()
{
List<IValue> parameters = new List<IValue>();
parameters.Add(new Parameter<int>(5));
parameters.Add(new Parameter<string>("abc"));
}
}
Marc Gravell [ Fr, 04 April 2008 16:15 ] [ ID #1935331 ]

Re: Generics and collections

Thank you for a very prompt answer.

This looks like it will do exactly what I want. I now need to go off and do
some further testing.

Again, thanks for your help.

Martin.


"Marc Gravell" <marc.gravell [at] gmail.com> wrote in message
news:eLgLo5llIHA.3940 [at] TK2MSFTNGP05.phx.gbl...
> Well, you can use object - otherwise you need to use a layer of
> abstraction, such as a pair of interfaces allowing both typed (generic)
> and untyped access:
>
> using System.Collections.Generic;
> using System;
> interface IValue
> {
> Type ValueType { get; }
> object Value { get; set; }
> }
> interface IValue<T> : IValue
> {
> new T Value { get; set; }
> }
> class Parameter<T> : IValue<T>
> {
> public Type ValueType
> {
> get { return typeof(T); }
> }
> private T value;
> public T Value
> {
> get { return this.value; }
> set { this.value = value; }
> }
> object IValue.Value
> {
> get { return Value; }
> set { Value = (T)value; }
> }
> public Parameter() { }
> public Parameter(T value) { Value = value; }
> }
>
>
> static class Program
> {
> static void Main()
> {
> List<IValue> parameters = new List<IValue>();
> parameters.Add(new Parameter<int>(5));
> parameters.Add(new Parameter<string>("abc"));
> }
> }
Martin Robins [ Fr, 04 April 2008 16:35 ] [ ID #1935332 ]

Re: Generics and collections

On Apr 4, 9:32=A0am, "Martin Robins" <martin at orpheus-solutions dot co
dot uk> wrote:
> I do not know if what I am trying to do is impossible, however since I can=
not work out how to do it I thought I would post it here in the hope of some=
assistance.
>
> Consider the following code ...
>
> =A0 =A0 using System;
>
> =A0 =A0 public class Parameter<T> {
>
> =A0 =A0 =A0 =A0 private T value;
>
> =A0 =A0 =A0 =A0 public Parameter() {
> =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 public Parameter(T value)
> =A0 =A0 =A0 =A0 =A0 =A0 : this() {
> =A0 =A0 =A0 =A0 =A0 =A0 this.value =3D value;
> =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 public T Value {
> =A0 =A0 =A0 =A0 =A0 =A0 get { return this.value; }
> =A0 =A0 =A0 =A0 =A0 =A0 set { this.value =3D value; }
> =A0 =A0 =A0 =A0 }
> =A0 =A0 }
>
> =A0 =A0 public class BooleanParameter : Parameter<Boolean> {
> =A0 =A0 }
>
> =A0 =A0 public class ByteParameter : Parameter<Byte> {
> =A0 =A0 }
>
> =A0 =A0 public class WordParameter : Parameter<UInt16> {
> =A0 =A0 }
>
> As you can see, this is a simple example where I am creating generic types=
that will all expose a 'Value' property, but each of the 'Value' properties=
will have a different data type.
>
> If I want to create collections for these types, again this is fairly basi=
c ...
>
> =A0 =A0 using System.Collections.ObjectModel;
>
> =A0 =A0 public class BooleanParameterCollection : Collection<BooleanParame=
ter> {
> =A0 =A0 }
>
> =A0 =A0 public class ByteParameterCollection : Collection<ByteParameter> {=

> =A0 =A0 }
>
> =A0 =A0 public class WordParameterCollection : Collection<WordParameter> {=

> =A0 =A0 }
>
> However, what I actually want is to create a collection of Parameter<?> ob=
jects; that is, a single typed collection that can contain BooleanParameter,=
ByteParameter or WordParameter objects intermingled with each other and the=
n determine which of the objects I am working with at run time.
>
> I have tried various combinations of interfaces and base classes, but all =
to no avail. Is this possible, if so, can anybody help me see the light?
>
> Thanks in advance.
>
> Martin.

You have two options, either you use Object as the type of the
collection and by doing so ignore any use of Generics in the first
place Or you make all your types implement a common interface, most
probably you can do this
ignacio.machin [ Fr, 04 April 2008 16:42 ] [ ID #1935333 ]

Re: Generics and collections

>
> class Parameter<T> : IValue<T>
> {

Could this be re-written as
class Parameter<T> : IValue

It compiles and runs this way, but that might be because the compiler
is filling a missing piece or 2.
tadmill [ Fr, 04 April 2008 19:38 ] [ ID #1935342 ]

Re: Generics and collections

Marc,

Great answer, does most of what I want to do, but is there a more reliable
way of setting the value when the Parameter<> object has been cast to the
IValue interface?

For example, setting the value of a Parameter<byte> to 16 results in an
error if the initial statement does not include the cast [p.Value = 21
instead of p.Value = (byte)21;] - the internal cast [this.Value = (T)value]
fails with an invalid cast exception.

I have also tried using
[TypeDescriptor.GetConverter(this.ValueType).ConvertFrom(val ue)] but this
fails also!

Thanks again.I have been struggling with this for a while now and I am now
much closer.


"Marc Gravell" <marc.gravell [at] gmail.com> wrote in message
news:eLgLo5llIHA.3940 [at] TK2MSFTNGP05.phx.gbl...
> Well, you can use object - otherwise you need to use a layer of
> abstraction, such as a pair of interfaces allowing both typed (generic)
> and untyped access:
>
> using System.Collections.Generic;
> using System;
> interface IValue
> {
> Type ValueType { get; }
> object Value { get; set; }
> }
> interface IValue<T> : IValue
> {
> new T Value { get; set; }
> }
> class Parameter<T> : IValue<T>
> {
> public Type ValueType
> {
> get { return typeof(T); }
> }
> private T value;
> public T Value
> {
> get { return this.value; }
> set { this.value = value; }
> }
> object IValue.Value
> {
> get { return Value; }
> set { Value = (T)value; }
> }
> public Parameter() { }
> public Parameter(T value) { Value = value; }
> }
>
>
> static class Program
> {
> static void Main()
> {
> List<IValue> parameters = new List<IValue>();
> parameters.Add(new Parameter<int>(5));
> parameters.Add(new Parameter<string>("abc"));
> }
> }
Martin Robins [ Fr, 04 April 2008 20:38 ] [ ID #1935348 ]

Re: Generics and collections

> but is there a more reliable way of setting the value when the Parameter<> object
> has been cast to the IValue interface?

Ultimately, no. TypeConverter is a reasonable fallback; another option
(especially for cases like int/byte) is Convert.ChangeType - see if
that helps.

Marc
Marc Gravell [ Sa, 05 April 2008 22:30 ] [ ID #1936054 ]

Re: Generics and collections

Thanks again Marc,

This seems to have done the trick nicely.

Martin.

"Marc Gravell" <marc.gravell [at] gmail.com> wrote in message
news:7535c790-e7f8-4e69-a825-e1304dbf9038 [at] n14g2000pri.google groups.com...
>> but is there a more reliable way of setting the value when the
>> Parameter<> object
>> has been cast to the IValue interface?
>
> Ultimately, no. TypeConverter is a reasonable fallback; another option
> (especially for cases like int/byte) is Convert.ChangeType - see if
> that helps.
>
> Marc
Martin Robins [ Sa, 05 April 2008 23:51 ] [ ID #1936055 ]

Re: Generics and collections

Glad to help ;-p
Marc Gravell [ Sa, 05 April 2008 23:56 ] [ ID #1936056 ]
Microsoft » microsoft.public.dotnet.general » Generics and collections

Vorheriges Thema: Development Tool Recommendations
Nächstes Thema: ListView and Framework 3.5 Examples?