Generic type converter class. Cant call static method of type T.

S

Steve Richter

in a generic class, can I code the class so that I can call a static
method of the generic class T?

In the ConvertFrom method of the generic TypeConvert class I want to
write, I have a call to the static Parse method of the conversion
class.
if (InValue is string)
return T.Parse((string)InValue);
else
return base.ConvertFrom(context, culture, InValue);

the compiler gives an error message saying "T is a type parameter
which cannot be used in the given context. Can I call statics of the
generic class?

thanks,

-Steve


public class GenericTypeConverter<T> : TypeConverter where T:class
{

// this TypeConverter can convert from string.
public override bool CanConvertFrom(
ITypeDescriptorContext context,
Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return base.CanConvertFrom(context, sourceType);
}

// convert from string to T
public override object ConvertFrom(
ITypeDescriptorContext context,
CultureInfo culture,
object InValue)
{
if (InValue is string)
return T.Parse((string)InValue);
else
return base.ConvertFrom(context, culture, InValue);
}

// Convert from T to string.
public override object ConvertTo(
ITypeDescriptorContext context,
CultureInfo culture,
object InValue,
Type destinationType)
{
if (destinationType == typeof(string))
{
T vlus = InValue as T ;
return (vlus.ToString());
}
else
return base.ConvertTo(context, culture, InValue,
destinationType);
}
}
 
J

Jon Skeet [C# MVP]

Steve Richter said:
in a generic class, can I code the class so that I can call a static
method of the generic class T?

No. There's nothing you can do which will guarantee that there will be
a static Parse method in T, so the compiler won't let you call it. (You
could do it by reflection, of course, but that's horrible.)
 
S

Steve Richter

No. There's nothing you can do which will guarantee that there will be
a static Parse method in T, so the compiler won't let you call it.

darn! I thought that is what generics/templates were all about? The
compiler plugs in the actual type and then compiles the code.

Couldn't there be a where T: constraint that specifies the static
methods the using class must implement?
public class GenericTypeConverter<T> where T:class, new( ), static
T Parse( string )

Types substituted into this generic class must be classes, be
newable, and have a static method Parse that returns T and accepts a
single argument of type string.

-Steve
 
J

Jon Skeet [C# MVP]

darn! I thought that is what generics/templates were all about? The
compiler plugs in the actual type and then compiles the code.

That's what C++ templates are about - .NET generics aren't the same as
templates. The IL is only generated for the parameterised form of the
type, and then the JIT converts that into native code when it needs to
(roughly speaking, once per value type and once for *all* reference
types).
Couldn't there be a where T: constraint that specifies the static
methods the using class must implement?

It's not inconceivable that it could be in a future version of .NET,
but it's not available now, certainly.

Jon
 
N

Nicholas Paldino [.NET/C# MVP]

Steve,

In addition to what Jon said, the only way I can think of to make this
work would be to use the type name (through reflection) of T to figure out
what method on the IConvertible implementation in the String class you
should call in order to produce the value you want.
 
P

Peter Duniho

No. There's nothing you can do which will guarantee that there will be
a static Parse method in T, so the compiler won't let you call it. (You
could do it by reflection, of course, but that's horrible.)

Can you please elaborate on this? The thing I'm confused about is that
even when you constrain T to be a class that does have Parse() method, you
still get the error. I don't see a way to call static methods of a class
T, even when you've constrained the class T to be a class with the
specific static method.

Either there's a way to call static methods in the generic class that I'm
not seeing, or there's some reason you can't call static methods even when
you have guaranteed the existence of the static method.

Either way, I need help. :)

Pete
 
J

Jon Skeet [C# MVP]

Peter Duniho said:
Can you please elaborate on this? The thing I'm confused about is that
even when you constrain T to be a class that does have Parse() method, you
still get the error. I don't see a way to call static methods of a class
T, even when you've constrained the class T to be a class with the
specific static method.

Well, you'd constrain T to derive from a particular class which had a
specific static method; that's not quite the same thing as saying that
T itself has the static method - depending on your view of a type
"having" a static method.

(It's slightly easier for a void method than for a method returning T
as described by the OP - just because Foo has a static Parse method
returning Foo, that doesn't mean that every derived type will have a
static Parse method returning an instance of itself.)

Either way, there isn't a way of doing it, I'm afraid. (Well, there's
reflection, but I'm assuming we're not including that.)
Either there's a way to call static methods in the generic class that I'm
not seeing, or there's some reason you can't call static methods even when
you have guaranteed the existence of the static method.

Either way, I need help. :)

No, there just isn't a way of calling static methods. Basically static
methods don't have any kind of polymorphism (unfortunately) and that's
a large part of what the constraints are for.

Note that from the implementation side of things, there would be a cost
to this. Currently, I believe the JITted code for, say, List<T> is
shared for all reference types, but a separate version is required for
each value type. If static methods were allowed, you'd need a separate
version for each reference type as well, as they'd be calling different
static methods. Only in the case where the generic type *did* call any
static methods, of course...
 
P

Peter Duniho

[...]
still get the error. I don't see a way to call static methods of a
class T, even when you've constrained the class T to be a class
with the specific static method.

Well, you'd constrain T to derive from a particular class which had a
specific static method; that's not quite the same thing as saying that
T itself has the static method - depending on your view of a type
"having" a static method.

To me, if a class inherits the method, it "has" the method. It may not
implement it, but it has an implementation of it that you can call. So
when I wrote "constrained the class T to be a class with the specific
static method" I did in fact simply mean that T, either by inheritance or
implementation, provides access to the static method in question.

In other words, the same rules that apply to instance methods. On the
face of it, I don't see any particular reason why static methods are
inherently different from instance methods, at least from a syntactical
point of view (I do understand the underlying implementation issues you
refer to later).
(It's slightly easier for a void method than for a method returning T
as described by the OP - just because Foo has a static Parse method
returning Foo, that doesn't mean that every derived type will have a
static Parse method returning an instance of itself.)

True. But is that issue unique to static methods? It seems like it's
more of an issue with respect to any method that returns a type the same
as the generic type T. For example, a cloning method. Obviously, however
the method is used in the generic class, it has to be constrained to
returning something that is known to exist at compile time. But as long
as that requirement is met, it should be possible. And the issue is the
same whether the method is static or not.
Either way, there isn't a way of doing it, I'm afraid. (Well, there's
reflection, but I'm assuming we're not including that.)

Yes. I avoid reflection as much as possible, in the same way I avoid
doing native Windows stuff as much as possible in .NET. I much prefer to
use the .NET Framework-provided mechanisms whenever possible, and if there
isn't one my next step is to try to implement what I'm doing some other
way that does use .NET Framework-provided mechanisms.
No, there just isn't a way of calling static methods. Basically static
methods don't have any kind of polymorphism (unfortunately) and that's
a large part of what the constraints are for.

Okay, I'll bite. Maybe I've been using generics in a naive manner, but
I'm missing the "that's a large part of what the constraints are for"
aspect of your comment. In what way do static methods fail to provide the
kind of polymorphism that is "a large part of what the constaints are
for"? Can you provide an example?
Note that from the implementation side of things, there would be a cost
to this. Currently, I believe the JITted code for, say, List<T> is
shared for all reference types, but a separate version is required for
each value type. If static methods were allowed, you'd need a separate
version for each reference type as well, as they'd be calling different
static methods. Only in the case where the generic type *did* call any
static methods, of course...

So I guess my question is "why can't you call static methods from generic
classes"? And it sounds as though the answer is simply that it would
complicate the implementation of generic classes. Is that correct? It's
not that it couldn't be done, but rather that it would change the
underlying implementation of generics in an unfavorable way?

Pete
 
J

Jon Skeet [C# MVP]

Peter Duniho said:
To me, if a class inherits the method, it "has" the method. It may not
implement it, but it has an implementation of it that you can call. So
when I wrote "constrained the class T to be a class with the specific
static method" I did in fact simply mean that T, either by inheritance or
implementation, provides access to the static method in question.
Right.

In other words, the same rules that apply to instance methods. On the
face of it, I don't see any particular reason why static methods are
inherently different from instance methods, at least from a syntactical
point of view (I do understand the underlying implementation issues you
refer to later).

I understand - and indeed it would occasionally be helpful to be able
to call static methods.
True. But is that issue unique to static methods? It seems like it's
more of an issue with respect to any method that returns a type the same
as the generic type T. For example, a cloning method. Obviously, however
the method is used in the generic class, it has to be constrained to
returning something that is known to exist at compile time. But as long
as that requirement is met, it should be possible. And the issue is the
same whether the method is static or not.

The point (not clearly made, unfortunately) is that the OP wouldn't be
able to specify that a particular method signature were required
whether it was a static method or an instance method. It's basically a
problem with the idea of specifying methods as constraints where the
type parameter is part of the parameter list or the return type.
Yes. I avoid reflection as much as possible, in the same way I avoid
doing native Windows stuff as much as possible in .NET. I much prefer to
use the .NET Framework-provided mechanisms whenever possible, and if there
isn't one my next step is to try to implement what I'm doing some other
way that does use .NET Framework-provided mechanisms.
:)


Okay, I'll bite. Maybe I've been using generics in a naive manner, but
I'm missing the "that's a large part of what the constraints are for"
aspect of your comment. In what way do static methods fail to provide the
kind of polymorphism that is "a large part of what the constaints are
for"? Can you provide an example?

Polymorphism lets me call a method declared in a base class, knowing
that the method may be overriden by a derived class (assuming it's
virtual, of course).

There's no concept in .NET of a virtual static method which can be
overridden in a derived class - if there are two static methods with
the same signature (one in the base class, one in the derived class),
they're completely unrelated as far as the compiler is concerned. (Note
that this isn't the case in Delphi, as far as I understand it.)

There's therefore a difference between inserting a call to
instanceOfT.SomeVirtualMethod();
and
T.StaticMethod();

- either the compiler needs to look for "extra" methods with the
appropriate signature, or you wouldn't get the pseudo-polymorphism
which is desired, and you might as well call the static method in the
class specified in the constraint.
So I guess my question is "why can't you call static methods from generic
classes"? And it sounds as though the answer is simply that it would
complicate the implementation of generic classes. Is that correct? It's
not that it couldn't be done, but rather that it would change the
underlying implementation of generics in an unfavorable way?

No, I think it's more than that. It would be sort of introducing
polymorphism to static methods "by the back door" *or* be not
particularly useful. Both options are quite clunky.

Now, if true polymorphism of static methods were ever introduced
somehow, then it would make a lot of sense for generics to be able to
pick up on that.
 
P

Peter Duniho

[...]
The point (not clearly made, unfortunately) is that the OP wouldn't be
able to specify that a particular method signature were required
whether it was a static method or an instance method. It's basically a
problem with the idea of specifying methods as constraints where the
type parameter is part of the parameter list or the return type.

So he has more than one problem. :) And yes, I do see the problem with
the method signature.
Polymorphism lets me call a method declared in a base class, knowing
that the method may be overriden by a derived class (assuming it's
virtual, of course).

I understand that much. :) And yet, I failed to apply that to the
discussion. Probably because my use of generics *is* somewhat simplistic
and doesn't take advantage of polymorphism.
[...]
- either the compiler needs to look for "extra" methods with the
appropriate signature, or you wouldn't get the pseudo-polymorphism
which is desired, and you might as well call the static method in the
class specified in the constraint.

Ah, I see. My use of generics much more often has to do with the simple
type-safeness of them, and allowing me to avoid explicitly casting things
in a generic collection, I've overlooked the more general uses, especially
as they relate to virtual methods. And of course you're right, in C#
currently there's no such thing as a virtual static method (I'm not even
sure how that would work, unless you start being able to call static
methods from an instance reference, or pass around an actual instance of
the type).
No, I think it's more than that. It would be sort of introducing
polymorphism to static methods "by the back door" *or* be not
particularly useful. Both options are quite clunky.

Well, I was thinking of more in the latter "not particularly useful" vein.

I think the main thing I was missing is that you can always just call the
constraint class's static method directly. So, for example, if you
constrained the generic to use T where T derived from class A that has
static method B, instead of writing T.B(), you could just as easily and
effectively write A.B().

In hindsight, it seems like a "duh" moment. But for some reason I just
wasn't putting the pieces together until now. Thanks for the help. :)

Pete
 

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