confused about generics and abstract classes

H

herpers

Hello,

I probably don't see the obvious, but maybe you can help me out of this
mess.

The following is my problem:
I created two classes NormDistribution and DiscDistribution. Both
classes provide an implemation of the operator +.

Now I want to write another generic class Plan<DType>, which can
accept NormDistribution and DiscDistribution for DType. And here comes
my problem. Class Plan must have a function like this:

public class Plan<DType>
{
public DType Demand1;
public DType Demand2;
public DType Demand3;

public void Optimize()
{
Demand3 = Demand1 + Demand2; // <- error CS0019
}
}

How can I solve the problem?
The background for this is, that my class Plan does some computations,
which are independant of the underling distribution type. The
computation differ only in the implementation of the basic operators +,
- and so on. I wanted to delegate the problem to the NormDistribtution
and DiscDistribution class, but somehow I can not get it to work.

Any ideas?

Thanks,
Sascha
 
C

Chris Nahr

The following is my problem:
I created two classes NormDistribution and DiscDistribution. Both
classes provide an implemation of the operator +.

Judging from your code, it looks as if you expected .NET/C# generics
to work like C++ generics -- but they don't. They use run-time
instantiation, not compile-time instantiation as in C++, so that they
can be used from different assemblies than the one they're defined in.

For this reason, it doesn't matter whether your _concrete_ types
define some method. Your _type argument_ must declare any methods
that you want to use in the generic class or method, via constraints.

And even so, you won't be able to use operators at all because .NET
generics do not currently accept operator restraints. You must define
a regular method for addition instead.

No offense, but I suggest you pick up the MSDN Library or a good book
(see my website) and read up on how .NET generics work. There's a lot
of gotchas for people who are used to C++ generics. Jeff Richter's
"CLR via C#" covers everything you need to know in this regard.
 
N

Nick Hounsome

Hello,

I probably don't see the obvious, but maybe you can help me out of this
mess.

The following is my problem:
I created two classes NormDistribution and DiscDistribution. Both
classes provide an implemation of the operator +.

Now I want to write another generic class Plan<DType>, which can
accept NormDistribution and DiscDistribution for DType. And here comes
my problem. Class Plan must have a function like this:

public class Plan<DType>
{
public DType Demand1;
public DType Demand2;
public DType Demand3;

public void Optimize()
{
Demand3 = Demand1 + Demand2; // <- error CS0019
}
}

How can I solve the problem?
The background for this is, that my class Plan does some computations,
which are independant of the underling distribution type. The
computation differ only in the implementation of the basic operators +,
- and so on. I wanted to delegate the problem to the NormDistribtution
and DiscDistribution class, but somehow I can not get it to work.

Any ideas?

Thanks,
Sascha

1) Either have your distribution classes derive from a common base or
implement a common interface (Let's call it "Common" either way).
2) Give Common an "public Common Add(Common other)" method
3) Force DType to be derived from (or implement) Common: "public class
Plan<DType> where DType: Common {...."
4) Demand3 = Demand1.Add(Demand2);

This isn't really satisfactory because you might as well forget about
generics and just work with "Common" using plain old polymorphism.

As Chris pointed out - even ignoring the issue of operators or methods you
cannot do the usual C++ stuff.

eg you cannot inject methods into a derived class with:

public class DiscDistribution : IAddable<DiscDistribution>
 
J

Jay B. Harlow [MVP - Outlook]

Nick,
| eg you cannot inject methods into a derived class with:
| public class DiscDistribution : IAddable<DiscDistribution>
Umm... Yes you can!

Try:

public interface IAddable<T>
{
T Add(T other);
}

public class DiscDistribution : IAddable<DiscDistribution>
{
public DiscDistribution Add(DiscDistribution other)
{
return null;
}
}

I use the above with IEquatable<T> all the time!


--
Hope this helps
Jay B. Harlow [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


|
| | > Hello,
| >
| > I probably don't see the obvious, but maybe you can help me out of this
| > mess.
| >
| > The following is my problem:
| > I created two classes NormDistribution and DiscDistribution. Both
| > classes provide an implemation of the operator +.
| >
| > Now I want to write another generic class Plan<DType>, which can
| > accept NormDistribution and DiscDistribution for DType. And here comes
| > my problem. Class Plan must have a function like this:
| >
| > public class Plan<DType>
| > {
| > public DType Demand1;
| > public DType Demand2;
| > public DType Demand3;
| >
| > public void Optimize()
| > {
| > Demand3 = Demand1 + Demand2; // <- error CS0019
| > }
| > }
| >
| > How can I solve the problem?
| > The background for this is, that my class Plan does some computations,
| > which are independant of the underling distribution type. The
| > computation differ only in the implementation of the basic operators +,
| > - and so on. I wanted to delegate the problem to the NormDistribtution
| > and DiscDistribution class, but somehow I can not get it to work.
| >
| > Any ideas?
| >
| > Thanks,
| > Sascha
| >
|
| 1) Either have your distribution classes derive from a common base or
| implement a common interface (Let's call it "Common" either way).
| 2) Give Common an "public Common Add(Common other)" method
| 3) Force DType to be derived from (or implement) Common: "public class
| Plan<DType> where DType: Common {...."
| 4) Demand3 = Demand1.Add(Demand2);
|
| This isn't really satisfactory because you might as well forget about
| generics and just work with "Common" using plain old polymorphism.
|
| As Chris pointed out - even ignoring the issue of operators or methods you
| cannot do the usual C++ stuff.
|
| eg you cannot inject methods into a derived class with:
|
| public class DiscDistribution : IAddable<DiscDistribution>
|
|
|
 
J

Jay B. Harlow [MVP - Outlook]

Sascha,
In addition to the other comments, I would define an interface that
supported the operation(s) needed, both classes would implement the
interface, Plan's DType parameter would be constrained by the interface,
something like:

// list the desired operations
public interface IAddable<T>
{
T Add(T other);
}

// constrain the type to the list of desired operations
public class Plan<DType> where DType : IAddable<DType>
{
public DType Demand1;
public DType Demand2;
public DType Demand3;

public void Optimize()
{
// use one of the desired operations
Demand3 = Demand1.Add(Demand2);
}
}


// indicate this type implements the desired operations
public class DiscDistribution : IAddable<DiscDistribution>
{

// implement the desired operation!
public DiscDistribution Add(DiscDistribution other)
{
return this + other;
}
public static DiscDistribution operator +(DiscDistribution lhs,
DiscDistribution rhs)
{
return ...
}
}

// indicate this type implements the desired operations
public class NormDistribution : IAddable<NormDistribution>
{

// implement the desired operation!
public NormDistribution Add(NormDistribution other)
{
return this + other;
}

public static NormDistribution operator + (NormDistribution lhs,
NormDistribution rhs)
{
return ...
}
}

The IAddable<DType> contraint on Plan<DType> is where all the "magic"
happens, it tells the compiler that any variables of DType within Plan will
have the methods listed in the interface!

--
Hope this helps
Jay B. Harlow [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| Hello,
|
| I probably don't see the obvious, but maybe you can help me out of this
| mess.
|
| The following is my problem:
| I created two classes NormDistribution and DiscDistribution. Both
| classes provide an implemation of the operator +.
|
| Now I want to write another generic class Plan<DType>, which can
| accept NormDistribution and DiscDistribution for DType. And here comes
| my problem. Class Plan must have a function like this:
|
| public class Plan<DType>
| {
| public DType Demand1;
| public DType Demand2;
| public DType Demand3;
|
| public void Optimize()
| {
| Demand3 = Demand1 + Demand2; // <- error CS0019
| }
| }
|
| How can I solve the problem?
| The background for this is, that my class Plan does some computations,
| which are independant of the underling distribution type. The
| computation differ only in the implementation of the basic operators +,
| - and so on. I wanted to delegate the problem to the NormDistribtution
| and DiscDistribution class, but somehow I can not get it to work.
|
| Any ideas?
|
| Thanks,
| Sascha
|
 
N

Nick Hounsome

1000 apologies - I was thinking of "class C<T> : T" or "C<A,B> : A<B>".

Your other post is indeed the way to go and the way that you would do
something similar in C++

Jay B. Harlow said:
Nick,
| eg you cannot inject methods into a derived class with:
| public class DiscDistribution : IAddable<DiscDistribution>
Umm... Yes you can!

Try:

public interface IAddable<T>
{
T Add(T other);
}

public class DiscDistribution : IAddable<DiscDistribution>
{
public DiscDistribution Add(DiscDistribution other)
{
return null;
}
}

I use the above with IEquatable<T> all the time!


--
Hope this helps
Jay B. Harlow [MVP - Outlook]
.NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


|
| | > Hello,
| >
| > I probably don't see the obvious, but maybe you can help me out of
this
| > mess.
| >
| > The following is my problem:
| > I created two classes NormDistribution and DiscDistribution. Both
| > classes provide an implemation of the operator +.
| >
| > Now I want to write another generic class Plan<DType>, which can
| > accept NormDistribution and DiscDistribution for DType. And here comes
| > my problem. Class Plan must have a function like this:
| >
| > public class Plan<DType>
| > {
| > public DType Demand1;
| > public DType Demand2;
| > public DType Demand3;
| >
| > public void Optimize()
| > {
| > Demand3 = Demand1 + Demand2; // <- error CS0019
| > }
| > }
| >
| > How can I solve the problem?
| > The background for this is, that my class Plan does some computations,
| > which are independant of the underling distribution type. The
| > computation differ only in the implementation of the basic operators
+,
| > - and so on. I wanted to delegate the problem to the NormDistribtution
| > and DiscDistribution class, but somehow I can not get it to work.
| >
| > Any ideas?
| >
| > Thanks,
| > Sascha
| >
|
| 1) Either have your distribution classes derive from a common base or
| implement a common interface (Let's call it "Common" either way).
| 2) Give Common an "public Common Add(Common other)" method
| 3) Force DType to be derived from (or implement) Common: "public class
| Plan<DType> where DType: Common {...."
| 4) Demand3 = Demand1.Add(Demand2);
|
| This isn't really satisfactory because you might as well forget about
| generics and just work with "Common" using plain old polymorphism.
|
| As Chris pointed out - even ignoring the issue of operators or methods
you
| cannot do the usual C++ stuff.
|
| eg you cannot inject methods into a derived class with:
|
| public class DiscDistribution : IAddable<DiscDistribution>
|
|
|
 
J

Jay B. Harlow [MVP - Outlook]

| 1000 apologies
Accepted, although I'm really offended!

| I was thinking of "class C<T> : T"

Correct:

Although the first time I saw "class C : B<C>" where B is a base class, I
scratched my head. As I think of the "C<T> : T" case... Which I find odd as
I follow the "class C : I<C>" without any problems...

| or "C<A,B> : A<B>".
This is allowed! ;-)

class A<T>
{
}

class B
{
}

class C<A,B> : A<B>
{
}

C<object, IEquatable<object>> x = new
C<object,IEquatable<object>>();

Depending on what you use for A & B, they could even be the same type, such
as:

class X : IEquatable<X>
{
public bool Equals(X other)
{
return false;
}
}

C<X, X> x = new C<X,X>();



--
Hope this helps
Jay B. Harlow [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| 1000 apologies - I was thinking of "class C<T> : T" or "C<A,B> : A<B>".
|
| Your other post is indeed the way to go and the way that you would do
| something similar in C++
|
| message | > Nick,
| > | eg you cannot inject methods into a derived class with:
| > | public class DiscDistribution : IAddable<DiscDistribution>
| > Umm... Yes you can!
| >
| > Try:
| >
| > public interface IAddable<T>
| > {
| > T Add(T other);
| > }
| >
| > public class DiscDistribution : IAddable<DiscDistribution>
| > {
| > public DiscDistribution Add(DiscDistribution other)
| > {
| > return null;
| > }
| > }
| >
| > I use the above with IEquatable<T> all the time!
| >
| >
| > --
| > Hope this helps
| > Jay B. Harlow [MVP - Outlook]
| > .NET Application Architect, Enthusiast, & Evangelist
| > T.S. Bradley - http://www.tsbradley.net
| >
| >
| > | > |
| > | | > | > Hello,
| > | >
| > | > I probably don't see the obvious, but maybe you can help me out of
| > this
| > | > mess.
| > | >
| > | > The following is my problem:
| > | > I created two classes NormDistribution and DiscDistribution. Both
| > | > classes provide an implemation of the operator +.
| > | >
| > | > Now I want to write another generic class Plan<DType>, which can
| > | > accept NormDistribution and DiscDistribution for DType. And here
comes
| > | > my problem. Class Plan must have a function like this:
| > | >
| > | > public class Plan<DType>
| > | > {
| > | > public DType Demand1;
| > | > public DType Demand2;
| > | > public DType Demand3;
| > | >
| > | > public void Optimize()
| > | > {
| > | > Demand3 = Demand1 + Demand2; // <- error CS0019
| > | > }
| > | > }
| > | >
| > | > How can I solve the problem?
| > | > The background for this is, that my class Plan does some
computations,
| > | > which are independant of the underling distribution type. The
| > | > computation differ only in the implementation of the basic operators
| > +,
| > | > - and so on. I wanted to delegate the problem to the
NormDistribtution
| > | > and DiscDistribution class, but somehow I can not get it to work.
| > | >
| > | > Any ideas?
| > | >
| > | > Thanks,
| > | > Sascha
| > | >
| > |
| > | 1) Either have your distribution classes derive from a common base or
| > | implement a common interface (Let's call it "Common" either way).
| > | 2) Give Common an "public Common Add(Common other)" method
| > | 3) Force DType to be derived from (or implement) Common: "public class
| > | Plan<DType> where DType: Common {...."
| > | 4) Demand3 = Demand1.Add(Demand2);
| > |
| > | This isn't really satisfactory because you might as well forget about
| > | generics and just work with "Common" using plain old polymorphism.
| > |
| > | As Chris pointed out - even ignoring the issue of operators or methods
| > you
| > | cannot do the usual C++ stuff.
| > |
| > | eg you cannot inject methods into a derived class with:
| > |
| > | public class DiscDistribution : IAddable<DiscDistribution>
| > |
| > |
| > |
| >
| >
|
|
 
N

Nick Hounsome

Jay B. Harlow said:
| 1000 apologies
Accepted, although I'm really offended!

| I was thinking of "class C<T> : T"

Correct:

Although the first time I saw "class C : B<C>" where B is a base class, I
scratched my head. As I think of the "C<T> : T" case... Which I find odd
as
I follow the "class C : I<C>" without any problems...

| or "C<A,B> : A<B>".
This is allowed! ;-)

I obviously haven't woken up yet!

Maybe I should quit for the day but.....

Contradict me on this then:

Although you can have "C : IAddable<C>" it's still not as useful as C++
templates because you can't have "C : Addable<C>" with an actual
implementation of the addition as you can with C++ rel_ops say.
 
J

Jay B. Harlow [MVP - Outlook]

|| 1000 apologies
| Accepted, although I'm really offended!

Doh! Double Doh!

I meant to say:

Accepted, although I'm really *NOT* offended!


--
Hope this helps
Jay B. Harlow [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


message || 1000 apologies
| Accepted, although I'm really offended!
|
|| I was thinking of "class C<T> : T"
|
| Correct:
|
| Although the first time I saw "class C : B<C>" where B is a base class, I
| scratched my head. As I think of the "C<T> : T" case... Which I find odd
as
| I follow the "class C : I<C>" without any problems...
|
|| or "C<A,B> : A<B>".
| This is allowed! ;-)
|
| class A<T>
| {
| }
|
| class B
| {
| }
|
| class C<A,B> : A<B>
| {
| }
|
| C<object, IEquatable<object>> x = new
| C<object,IEquatable<object>>();
|
| Depending on what you use for A & B, they could even be the same type,
such
| as:
|
| class X : IEquatable<X>
| {
| public bool Equals(X other)
| {
| return false;
| }
| }
|
| C<X, X> x = new C<X,X>();
|
|
|
| --
| Hope this helps
| Jay B. Harlow [MVP - Outlook]
| .NET Application Architect, Enthusiast, & Evangelist
| T.S. Bradley - http://www.tsbradley.net
|
|
| || 1000 apologies - I was thinking of "class C<T> : T" or "C<A,B> : A<B>".
||
|| Your other post is indeed the way to go and the way that you would do
|| something similar in C++
||
|| message || > Nick,
|| > | eg you cannot inject methods into a derived class with:
|| > | public class DiscDistribution : IAddable<DiscDistribution>
|| > Umm... Yes you can!
|| >
|| > Try:
|| >
|| > public interface IAddable<T>
|| > {
|| > T Add(T other);
|| > }
|| >
|| > public class DiscDistribution : IAddable<DiscDistribution>
|| > {
|| > public DiscDistribution Add(DiscDistribution other)
|| > {
|| > return null;
|| > }
|| > }
|| >
|| > I use the above with IEquatable<T> all the time!
|| >
|| >
|| > --
|| > Hope this helps
|| > Jay B. Harlow [MVP - Outlook]
|| > .NET Application Architect, Enthusiast, & Evangelist
|| > T.S. Bradley - http://www.tsbradley.net
|| >
|| >
|| > || > |
|| > | || > | > Hello,
|| > | >
|| > | > I probably don't see the obvious, but maybe you can help me out of
|| > this
|| > | > mess.
|| > | >
|| > | > The following is my problem:
|| > | > I created two classes NormDistribution and DiscDistribution. Both
|| > | > classes provide an implemation of the operator +.
|| > | >
|| > | > Now I want to write another generic class Plan<DType>, which can
|| > | > accept NormDistribution and DiscDistribution for DType. And here
| comes
|| > | > my problem. Class Plan must have a function like this:
|| > | >
|| > | > public class Plan<DType>
|| > | > {
|| > | > public DType Demand1;
|| > | > public DType Demand2;
|| > | > public DType Demand3;
|| > | >
|| > | > public void Optimize()
|| > | > {
|| > | > Demand3 = Demand1 + Demand2; // <- error CS0019
|| > | > }
|| > | > }
|| > | >
|| > | > How can I solve the problem?
|| > | > The background for this is, that my class Plan does some
| computations,
|| > | > which are independant of the underling distribution type. The
|| > | > computation differ only in the implementation of the basic
operators
|| > +,
|| > | > - and so on. I wanted to delegate the problem to the
| NormDistribtution
|| > | > and DiscDistribution class, but somehow I can not get it to work.
|| > | >
|| > | > Any ideas?
|| > | >
|| > | > Thanks,
|| > | > Sascha
|| > | >
|| > |
|| > | 1) Either have your distribution classes derive from a common base or
|| > | implement a common interface (Let's call it "Common" either way).
|| > | 2) Give Common an "public Common Add(Common other)" method
|| > | 3) Force DType to be derived from (or implement) Common: "public
class
|| > | Plan<DType> where DType: Common {...."
|| > | 4) Demand3 = Demand1.Add(Demand2);
|| > |
|| > | This isn't really satisfactory because you might as well forget about
|| > | generics and just work with "Common" using plain old polymorphism.
|| > |
|| > | As Chris pointed out - even ignoring the issue of operators or
methods
|| > you
|| > | cannot do the usual C++ stuff.
|| > |
|| > | eg you cannot inject methods into a derived class with:
|| > |
|| > | public class DiscDistribution : IAddable<DiscDistribution>
|| > |
|| > |
|| > |
|| >
|| >
||
||
|
|
 
H

herpers

Hi everybody,

thanks for all the good answers. Even though I know my way around in
c/c++ I feel like a beginner in c#. I think about your soloutions and
will implement them.

Thanks,
Sascha
 
J

Jay B. Harlow [MVP - Outlook]

Nick,
I not suggesting that Generics are "As useful" as C++ templates. I don't
believe I suggested anything either way. Now that you bring it up; my
feeling is: Although Generics are missing some features, most notably for me
operator constraints, I think Generics have learned from the mistakes of
templates & have a stronger implementation. Although I do find it extremely
handy in C++/CLI to be able to use both templates & generics in a solution;
including templated generic classes & generic templated classes. IMHO the
problem domain of templates & the problem domain of generics although
largely overlapping does not wholly contain each other! Remember Generics
are a runtime feature trying to solve a runtime problem, while Templates are
a compile time feature not concerned with the runtime problem. The generic
type itself is expanded once by the compiler into its assembly. Users of the
generic template simply refer to this assembly. The runtime will example the
generic type itself as needed. Templates get expanded into each assembly
meaning that a templated Nullable<Int32> in assembly one is a distinct type
from a template Nullable<Int32> in assembly two.

FWIW: I'm very curios on how the "operator constraint" problem will be
solved as IMHO its not as simply as it appears, some types (Int32) use
specific IL opcodes for each operator, while other types (Decimal) use
operator overloading. Currently the compiler itself decides to use an opcode
or call the specific method. This won't work per se with generics as a
generic type is compiled once into an assembly...

| Although you can have "C : IAddable<C>" it's still not as useful as C++
| templates because you can't have "C : Addable<C>" with an actual
| implementation of the addition as you can with C++ rel_ops say.
I take it you mean something like:

class Addable<T>
{
public static Addable<T> operator +(Addable<T> lhs, Addable<T>
rhs)
{
return ...;
}
public static T operator +(T lhs, T rhs)
{
return ...;
}
}

I'm not seeing a solution without an implicit conversion being defined. The
first operator above wants an implicit conversion defined, the second wants
one of the parameters to be Addable<T>.

You can define conversion operators in a generic type such as Addable<T>
(Nullable<T> uses them):

public static implicit operator T(Addable<T> other)
{
return default(T);
}

However in the above example I then get a CS0457 "Ambiguous user defined
conversions" error.

FWIW: This is the code where I was using the above:

class C : Addable<C>
{
}

C x = new C();
C y = new C();
C z = x + y;

Unfortunately I am far from a Generic expert, I may be missing something
simple in the above to get it to work. If I have time later maybe I will
look at it more then.

--
Hope this helps
Jay B. Harlow [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


|
| message | >| 1000 apologies
| > Accepted, although I'm really offended!
| >
| > | I was thinking of "class C<T> : T"
| >
| > Correct:
| >
| > Although the first time I saw "class C : B<C>" where B is a base class,
I
| > scratched my head. As I think of the "C<T> : T" case... Which I find odd
| > as
| > I follow the "class C : I<C>" without any problems...
| >
| > | or "C<A,B> : A<B>".
| > This is allowed! ;-)
|
| I obviously haven't woken up yet!
|
| Maybe I should quit for the day but.....
|
| Contradict me on this then:
|
| Although you can have "C : IAddable<C>" it's still not as useful as C++
| templates because you can't have "C : Addable<C>" with an actual
| implementation of the addition as you can with C++ rel_ops say.
|
|
 
C

Chris Nahr

FWIW: I'm very curios on how the "operator constraint" problem will be
solved as IMHO its not as simply as it appears, some types (Int32) use
specific IL opcodes for each operator, while other types (Decimal) use
operator overloading. Currently the compiler itself decides to use an opcode
or call the specific method. This won't work per se with generics as a
generic type is compiled once into an assembly...

That is true, and numerics are really the #1 reason for having
operator constraints in the first place. I think one of the related
entries in the MSDN Feedback Center suggests that the BCL provide a
special construct to express "type T is a numeric type" rather than a
general operator constraint. That's more useful in my opinion, but
then again I'm not a big fan of arbitrary operator overloading!
 
A

alwin

Op Thu, 11 May 2006 17:10:42 +0200 schreef Chris Nahr
That is true, and numerics are really the #1 reason for having
operator constraints in the first place. I think one of the related
entries in the MSDN Feedback Center suggests that the BCL provide a
special construct to express "type T is a numeric type" rather than a
general operator constraint. That's more useful in my opinion, but
then again I'm not a big fan of arbitrary operator overloading!

they should make it possible to use operators in interfaces (can anyone
tell me why that is not possible?) so we can have an Inumeric or something
and let float/double/uint32 implement that.

i tried to use generics for a part of my 3d engine but i got frustrated
while using generics. now i'm implementing interpolation routines for each
type, something generics should prevent.

alwin
 
C

Chris Nahr

they should make it possible to use operators in interfaces (can anyone
tell me why that is not possible?)

Yes. Operators are static methods, and interfaces only support
instance methods. There you have it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top