By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,701 Members | 2,021 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,701 IT Pros & Developers. It's quick & easy.

Is it possible to call a static method in the type class of a generic class?

P: n/a

I have a class SwatchPanel which takes Swatch as a parameter type. How can I call a static function within the Swatch class?

For example the code below fails on TSwatch.Exists. How can I get the call to work?

Exists is a method within the Swatch class NOT the SwatchPanel class.

Is this possible?
Suggestions would be very welcome.

Thanks,
Steve


public class SwatchPanel<TSwatch> : System.Windows.Forms.Panel where TSwatch : Swatch
{
protected virtual bool SetOkButtonState()
{
if (TSwatch.Exists(ColorDescription))
do something
}
}
Dec 8 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
steve bull <bu****@comcast.net> wrote:
I have a class SwatchPanel which takes Swatch as a parameter type.
How can I call a static function within the Swatch class?


Why not just call Swatch.Exists, i.e. don't use the generic argument at
all? You won't be able to use an "overridden" version of Swatch.Foo,
but then you can't override static methods anyway.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 8 '05 #2

P: n/a

it seems to me that the implementation of generics allows nothing but the most trivial of exercises to be done - without a means of
doing anything different based on the type allows only duplication and little variation.
For example if I want to write
public class SwatchPanel<TSwatch> : System.Windows.Forms.Panel where TSwatch : Swatch
{
List<TSwatch> swatchList;

public MethodA
{
Swatch.Write(swatchList);
}
}
to have different methods for writing out the swatches based on type. the compiler does not appear to let me.
I cannot say TSwatch.Write and when I write the following under the Swatch class
public class Swatch
{
public static void Write(List<Swatch> colorSwatchList)
{
write to swatch file
}

public static void Write(List<ColorSwatch> colorSwatchList)
{
write to color swatch file
}

public static void Write(List<ShadeSwatch> shadeSwatchList)
{
write to shade swatch file
}
}
the compiler tells me

Can't convert from 'System.Collections.Generic.List<TSwatch>' to 'System.Collections.Generic.List<NewControls.Swatc h>'

it always picks up the 1st override. If I switch the Swatch override with the ColorSwatch override it will want to convert to a
ColorSwatch generic list.


Maybe I am doing something very stupid here but it appears to be very difficult to do anything of any use with generics except
cookie cutting. They are a brain dead implementation.

If I make SwatchPanel a normal class and derive classes from it I can do everything all of the above w/o problem. Then the problem
is with making the Swatch.Write work with List<Swatch> swatchList. Each child class then has to convert from List<Swatch> to
List<ColorSwatch> etc when it wants to do the actual write in the method appropriate to it.

I am sorry if this is not the place to bring this up. But the implementation seems pretty poorly thought out.
Thanks,

Steve


On Thu, 8 Dec 2005 01:56:38 -0000, Jon Skeet [C# MVP] <sk***@pobox.com> wrote:
steve bull <bu****@comcast.net> wrote:
I have a class SwatchPanel which takes Swatch as a parameter type.
How can I call a static function within the Swatch class?


Why not just call Swatch.Exists, i.e. don't use the generic argument at
all? You won't be able to use an "overridden" version of Swatch.Foo,
but then you can't override static methods anyway.

Dec 8 '05 #3

P: n/a
steve bull <bu****@comcast.net> wrote:
it seems to me that the implementation of generics allows nothing but
the most trivial of exercises to be done - without a means of doing
anything different based on the type allows only duplication and
little variation.
That's not true at all. It doesn't allow the kind of templating C++
does, but frankly I'm glad of that.

For example if I want to write

public class SwatchPanel<TSwatch> : System.Windows.Forms.Panel where
TSwatch : Swatch
{
List<TSwatch> swatchList;

public MethodA
{
Swatch.Write(swatchList);
}
}
to have different methods for writing out the swatches based on type.
the compiler does not appear to let me. I cannot say TSwatch.Write
and when I write the following under the Swatch class
<snip>

Indeed. And that would be a bad way of writing it, IMO. It looks like
you want polymorphism at that stage - either have a class which
encapsulates a list of Swatches (generically) and override the
behaviour appropriately, or have one Write method which uses
polymorphism on the Swatch class to work out how to write each entry.

Alternatively, have an instance method in SwatchPanel which writes its
list out.
Maybe I am doing something very stupid here but it appears to be very
difficult to do anything of any use with generics except cookie
cutting. They are a brain dead implementation.
Cookie-cutting is a good example of exactly what generics are for. The
way you're trying to do things isn't how they're intended to be used,
but that doesn't mean generics are bad. What you're trying to do breaks
object orientation in various ways - for instance, by having a set of
static methods in the base class, you're including knowledge of each of
the subclasses into Swatch into the that base class, when that
knowledge should either be in the subclasses themselves, or at worst
the specialised subclasses of SwatchPanel.
If I make SwatchPanel a normal class and derive classes from it I can
do everything all of the above w/o problem. Then the problem is with
making the Swatch.Write work with List<Swatch> swatchList. Each child
class then has to convert from List<Swatch> to List<ColorSwatch> etc
when it wants to do the actual write in the method appropriate to it.

I am sorry if this is not the place to bring this up. But the
implementation seems pretty poorly thought out.


There are limitations which are genuinely problematic, but I don't
think I'd agree that anything you've brought up so far is actually a
problem with generics.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 8 '05 #4

P: n/a
Jon wrote:
steve bull <bu****@comcast.net> wrote:
it seems to me that the implementation of generics allows nothing but
the most trivial of exercises to be done - without a means of doing
anything different based on the type allows only duplication and
little variation.
That's not true at all. It doesn't allow the kind of templating C++
does, but frankly I'm glad of that.


I must say I agree with Steve. Generics seem to be useful for writing
typesafe containers, avoiding casts, and not much else. They'd be
capable of so much more if only we had better constraints. If he could
write, for example:

public class SwatchPanel<TSwatch> : Panel
where TSwatch has static void Write(List<TSwatch> foo)

Then this would be no problem.

As it is, we can't even write a generic Sum() function without
resorting to all kinds of ugly hacks, because the compiler can't see
the similarity between adding two ints and adding two floats. (We can
write a generic Max(), but only because the framework designers had the
foresight to make the basic types implement IComparable.)
Indeed. And that would be a bad way of writing it, IMO. It looks like
you want polymorphism at that stage - either have a class which
encapsulates a list of Swatches (generically) and override the
behaviour appropriately, or have one Write method which uses
polymorphism on the Swatch class to work out how to write each entry.


I agree that in this case, static methods are the wrong way to go. I'd
prefer the former solution, but it has the disadvantage that the list
class can't be located and instantiated automatically by the panel
without using reflection. You'd have to either construct the list
before the panel and pass it in to the constructor, or make the list
class an additional type parameter of SwatchPanel (with a new()
constraint).

Jesse

Dec 8 '05 #5

P: n/a
Jesse McGrew wrote:
Jon wrote:
steve bull <bu****@comcast.net> wrote:
it seems to me that the implementation of generics allows nothing but
the most trivial of exercises to be done - without a means of doing
anything different based on the type allows only duplication and
little variation.
That's not true at all. It doesn't allow the kind of templating C++
does, but frankly I'm glad of that.


I must say I agree with Steve. Generics seem to be useful for writing
typesafe containers, avoiding casts, and not much else.


Well, I don't think that's quite true - but even if it were, isn't that
still a huge leap forward? Steve seems to be dismissing generics as
only useful in "trivial" situations, whereas I use collections the
whole time in real applications.
They'd be
capable of so much more if only we had better constraints. If he could
write, for example:

public class SwatchPanel<TSwatch> : Panel
where TSwatch has static void Write(List<TSwatch> foo)

Then this would be no problem.
Absolutely. And the language would be a lot more complicated, which is
something I don't like.

There are all kinds of things it would be nice to have contracts for -
it would be nice if an interface could specify the constructors or
static methds which must be available, for instance, so that plugins
loaded reflectively could provide methods of being instantiated
appropriately. However, once you start putting things
As it is, we can't even write a generic Sum() function without
resorting to all kinds of ugly hacks, because the compiler can't see
the similarity between adding two ints and adding two floats. (We can
write a generic Max(), but only because the framework designers had the
foresight to make the basic types implement IComparable.)


Yes, generics fails pretty badly in terms of operators.
Indeed. And that would be a bad way of writing it, IMO. It looks like
you want polymorphism at that stage - either have a class which
encapsulates a list of Swatches (generically) and override the
behaviour appropriately, or have one Write method which uses
polymorphism on the Swatch class to work out how to write each entry.


I agree that in this case, static methods are the wrong way to go. I'd
prefer the former solution, but it has the disadvantage that the list
class can't be located and instantiated automatically by the panel
without using reflection. You'd have to either construct the list
before the panel and pass it in to the constructor, or make the list
class an additional type parameter of SwatchPanel (with a new()
constraint).


Yes. There are certainly issues there. I'd want to take a look at the
whole problem in a larger context, however. There may well be more
elegant solutions to what actually needs to be achieved if you move
further away from the existing attempted design.

Jon

Dec 8 '05 #6

P: n/a
"steve bull" <bu****@comcast.net> wrote in message
news:mo********************************@4ax.com...

it seems to me that the implementation of generics allows nothing but the
most trivial of exercises to be done - without a means of
doing anything different based on the type allows only duplication and
little variation.
For example if I want to write
public class SwatchPanel<TSwatch> : System.Windows.Forms.Panel where
TSwatch : Swatch
{
List<TSwatch> swatchList;

public MethodA
{
Swatch.Write(swatchList);
}
}
to have different methods for writing out the swatches based on type. the
compiler does not appear to let me.
I cannot say TSwatch.Write and when I write the following under the Swatch
class
public class Swatch
{
public static void Write(List<Swatch> colorSwatchList)
{
write to swatch file
}

public static void Write(List<ColorSwatch> colorSwatchList)
{
write to color swatch file
}

public static void Write(List<ShadeSwatch> shadeSwatchList)
{
write to shade swatch file
}
}
the compiler tells me

Can't convert from 'System.Collections.Generic.List<TSwatch>' to
'System.Collections.Generic.List<NewControls.Swatc h>'

it always picks up the 1st override. If I switch the Swatch override with
the ColorSwatch override it will want to convert to a
ColorSwatch generic list.


Maybe I am doing something very stupid here but it appears to be very
difficult to do anything of any use with generics except
cookie cutting. They are a brain dead implementation.

If I make SwatchPanel a normal class and derive classes from it I can do
everything all of the above w/o problem. Then the problem
is with making the Swatch.Write work with List<Swatch> swatchList. Each
child class then has to convert from List<Swatch> to
List<ColorSwatch> etc when it wants to do the actual write in the method
appropriate to it.

I am sorry if this is not the place to bring this up. But the
implementation seems pretty poorly thought out.
Thanks,

Steve


The issue with what you are trying to I believe is because determining which
overload of a method should be used is determined at COMPILE time. However,
information about the generic type will not be determined until runtime, so
the compiler has no way to use the other overloads. The only determination
that can be made at compile time is that TSwatch must be a Swatch, so the
first overload is used.

--
Adam Clauss
Dec 8 '05 #7

P: n/a
On Thu, 8 Dec 2005 07:13:21 -0000, Jon Skeet [C# MVP] <sk***@pobox.com> wrote:


to have different methods for writing out the swatches based on type.
the compiler does not appear to let me. I cannot say TSwatch.Write
and when I write the following under the Swatch class
<snip>

Indeed. And that would be a bad way of writing it, IMO. It looks like
you want polymorphism at that stage - either have a class which
encapsulates a list of Swatches (generically) and override the
behaviour appropriately, or have one Write method which uses
polymorphism on the Swatch class to work out how to write each entry.

the problem with this suggestion is that it just pushes the problem down a level.
e.g. if I encapsulated the swatchList as SwatchList<TSwatch> and call swatchList.Write() I would still need to get some
constant information associated with that swatch type in the new class. Which is the same problem in a different place.


Alternatively, have an instance method in SwatchPanel which writes its
list out.

I am not quite sure what you mean here. Do you mean write routines

Write(List<ColorSwatch) swatchList)
Write(List<ShadeSwatch> swatchList) etc?

If so it would seem to me that it would break all the reasons for using generics in the 1st place.

I still don't see any way forward with this - I seem to be better off going back to subclassing and using a non-typesafe
array. At least it avoids all these issues even though it is far from ideal.

Thanks for all the feedback.

Steve

Dec 8 '05 #8

P: n/a
steve bull <bu****@comcast.net> wrote:
Indeed. And that would be a bad way of writing it, IMO. It looks like
you want polymorphism at that stage - either have a class which
encapsulates a list of Swatches (generically) and override the
behaviour appropriately, or have one Write method which uses
polymorphism on the Swatch class to work out how to write each entry.
the problem with this suggestion is that it just pushes the problem
down a level. e.g. if I encapsulated the swatchList as
SwatchList<TSwatch> and call swatchList.Write() I would still need to
get some constant information associated with that swatch type in the
new class. Which is the same problem in a different place.


No, it's not - because then you could ask for *instance* information,
and that could be overridden. If you have ColorSwatchList which extends
SwatchList<ColorSwatch>, that could override appropriate methods to say
what headers to use etc.
Alternatively, have an instance method in SwatchPanel which writes its
list out.

I am not quite sure what you mean here. Do you mean write routines

Write(List<ColorSwatch) swatchList)
Write(List<ShadeSwatch> swatchList) etc?


Just WriteList(), given that it would already know the list internally.
You wouldn't have different methods - you'd have one method which could
be overridden in classes which needed to.
If so it would seem to me that it would break all the reasons for
using generics in the 1st place.

I still don't see any way forward with this - I seem to be better off
going back to subclassing and using a non-typesafe array. At least it
avoids all these issues even though it is far from ideal.


I would try looking at the problem from scratch, and try to avoid using
overloading as a poor man's form of polymorphism - that's not what it's
there for.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Dec 8 '05 #9

P: n/a
"steve bull" wrote:
On Thu, 8 Dec 2005 07:13:21 -0000, Jon Skeet [C# MVP] <sk***@pobox.com> wrote:


to have different methods for writing out the swatches based on type.
the compiler does not appear to let me. I cannot say TSwatch.Write
and when I write the following under the Swatch class
<snip>

Indeed. And that would be a bad way of writing it, IMO. It looks like
you want polymorphism at that stage - either have a class which
encapsulates a list of Swatches (generically) and override the
behaviour appropriately, or have one Write method which uses
polymorphism on the Swatch class to work out how to write each entry.

the problem with this suggestion is that it just pushes the problem down a level.
e.g. if I encapsulated the swatchList as SwatchList<TSwatch> and call swatchList.Write() I would still need to get some
constant information associated with that swatch type in the new class. Which is the same problem in a different place.


no it doesn't. here's what Jon has suggested

method1, have different speicialized swatch list classes
ColorSwatchList : SwatchList<ColorSwatch>
ShadeSwatchList : SwatchList<ShadeSwatch>
and each list will have a method Write() that knows how to write each entry
one by one.

method2, have each implementation of Swatch know how to write itself. then
the list will delegate the write operation to the individual entries.

both of which are the proper way of handle polymorphism. static methods are
not polymorphic. overloading them is not the right way to solve the problem.



Alternatively, have an instance method in SwatchPanel which writes its
list out.

I am not quite sure what you mean here. Do you mean write routines

Write(List<ColorSwatch) swatchList)
Write(List<ShadeSwatch> swatchList) etc?

If so it would seem to me that it would break all the reasons for using generics in the 1st place.

I still don't see any way forward with this - I seem to be better off going back to subclassing and using a non-typesafe
array. At least it avoids all these issues even though it is far from ideal.

Thanks for all the feedback.

Steve

Dec 8 '05 #10

P: n/a


Thank you for taking up so much of your time to make all these suggestions.

I don't think generics are the natural way of dealing with my problem. The way I originally developed the SwatchPanel as
a series of subclasses worked pretty well where SwatchPanel did most of the work. Thinking about what you have talked
about leads me to believe that the original reason for trying generics might be overcome with some of your suggestions.

Using subclasses only had the problem of passing around a List<Swatch> to the read/write routines which I wanted to be
cast to the swatch type appropriate to those routines. I think that encapsulating the swatchList as you described would
work there as well. What I have also works, it doesn't break any OO rules I don't think and I don't need to retest
everything again.

In fact, using generics, read/write wasn't the only problem I had - just the biggest of them. For example when I draw
the swatches on the panel they could be different sizes depending on the type of swatch and this would be a SwatchPanel
parameter really as I could decide, and have, to write other widgets which have different sizes that they would have the
swatches draw themselves.

Your explanations have been much appreciated.

Thanks,
Steve


On Thu, 8 Dec 2005 18:05:29 -0000, Jon Skeet [C# MVP] <sk***@pobox.com> wrote:
steve bull <bu****@comcast.net> wrote:
>Indeed. And that would be a bad way of writing it, IMO. It looks like
>you want polymorphism at that stage - either have a class which
>encapsulates a list of Swatches (generically) and override the
>behaviour appropriately, or have one Write method which uses
>polymorphism on the Swatch class to work out how to write each entry.


the problem with this suggestion is that it just pushes the problem
down a level. e.g. if I encapsulated the swatchList as
SwatchList<TSwatch> and call swatchList.Write() I would still need to
get some constant information associated with that swatch type in the
new class. Which is the same problem in a different place.


No, it's not - because then you could ask for *instance* information,
and that could be overridden. If you have ColorSwatchList which extends
SwatchList<ColorSwatch>, that could override appropriate methods to say
what headers to use etc.
>Alternatively, have an instance method in SwatchPanel which writes its
>list out.

I am not quite sure what you mean here. Do you mean write routines

Write(List<ColorSwatch) swatchList)
Write(List<ShadeSwatch> swatchList) etc?


Just WriteList(), given that it would already know the list internally.
You wouldn't have different methods - you'd have one method which could
be overridden in classes which needed to.
If so it would seem to me that it would break all the reasons for
using generics in the 1st place.

I still don't see any way forward with this - I seem to be better off
going back to subclassing and using a non-typesafe array. At least it
avoids all these issues even though it is far from ideal.


I would try looking at the problem from scratch, and try to avoid using
overloading as a poor man's form of polymorphism - that's not what it's
there for.


Dec 8 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.