Generics and collections

Generics and collections

am 04.04.2008 15:32:48 von Martin Robins

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 {

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 {
}

public class ByteParameter : Parameter {
}

public class WordParameter : Parameter {
}

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 {
}

public class ByteParameterCollection : Collection {
}

public class WordParameterCollection : Collection {
}

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



charset=3Diso-8859-1">




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

 

Consider the following code =
....

size=3D2> 
size=3D2>
    using size=3D1> System;

 

    public color=3D#0000ff>class Parameter
size=3D1><T> {

 

       =20
private
T value;

 

       =20
public
Parameter() {

        }

 

       =20
public
Parameter(T =
value)

       =20
    : this() {
size=3D1>

       =20
    this
.value =
value;

        }

 

       =20
public
T Value {

       =20
    get
{ return =
color=3D#0000ff>this.value; =
}

       =20
    set
{ this.value =
=3D color=3D#0000ff>value; =
}

        }

    }

 

    public color=3D#0000ff>class color=3D#2b91af>BooleanParameter : color=3D#2b91af>Parameter< color=3D#2b91af>Boolean size=3D1>> {

    }

 

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

    }

 

    public
color=3D#0000ff>class
WordParameter =
: color=3D#2b91af>Parameter< color=3D#2b91af>UInt16 size=3D1>> {

    }

 

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

 

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

size=3D2> 
size=3D2>
    using size=3D1> =
System.Collections.ObjectModel;

 

    public
color=3D#0000ff>class
color=3D#2b91af>BooleanParameterCollection=20
: Collection< color=3D#2b91af>BooleanParameter size=3D2>>=20
{

    }

 

    public
color=3D#0000ff>class
color=3D#2b91af>ByteParameterCollection :=20
Collection< color=3D#2b91af>ByteParameter> =
{

    }

 

    public
color=3D#0000ff>class
color=3D#2b91af>WordParameterCollection :=20
Collection< color=3D#2b91af>WordParameter> =
{

    }

 

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

 

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

 

Thanks in advance.

 

Martin.


------=_NextPart_000_0006_01C89660.C1AA00F0--

Re: Generics and collections

am 04.04.2008 16:15:57 von Marc Gravell

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 : IValue
{
new T Value { get; set; }
}
class Parameter : IValue
{
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 parameters = new List();
parameters.Add(new Parameter(5));
parameters.Add(new Parameter("abc"));
}
}

Re: Generics and collections

am 04.04.2008 16:35:12 von Martin Robins

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" wrote in message
news:eLgLo5llIHA.3940@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 : IValue
> {
> new T Value { get; set; }
> }
> class Parameter : IValue
> {
> 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 parameters = new List();
> parameters.Add(new Parameter(5));
> parameters.Add(new Parameter("abc"));
> }
> }

Re: Generics and collections

am 04.04.2008 16:42:13 von ignacio.machin

On Apr 4, 9:32=A0am, "Martin Robins" 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 {
>
> =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 {
> =A0 =A0 }
>
> =A0 =A0 public class ByteParameter : Parameter {
> =A0 =A0 }
>
> =A0 =A0 public class WordParameter : Parameter {
> =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 ter> {
> =A0 =A0 }
>
> =A0 =A0 public class ByteParameterCollection : Collection {=

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

> =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

Re: Generics and collections

am 04.04.2008 19:38:46 von tadmill

>
> class Parameter : IValue
> {

Could this be re-written as
class Parameter : IValue

It compiles and runs this way, but that might be because the compiler
is filling a missing piece or 2.

Re: Generics and collections

am 04.04.2008 20:38:30 von Martin Robins

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 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" wrote in message
news:eLgLo5llIHA.3940@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 : IValue
> {
> new T Value { get; set; }
> }
> class Parameter : IValue
> {
> 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 parameters = new List();
> parameters.Add(new Parameter(5));
> parameters.Add(new Parameter("abc"));
> }
> }

Re: Generics and collections

am 05.04.2008 22:30:50 von Marc Gravell

> 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

Re: Generics and collections

am 05.04.2008 23:51:58 von Martin Robins

Thanks again Marc,

This seems to have done the trick nicely.

Martin.

"Marc Gravell" wrote in message
news:7535c790-e7f8-4e69-a825-e1304dbf9038@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

Re: Generics and collections

am 05.04.2008 23:56:55 von Marc Gravell

Glad to help ;-p