Generics: static member invocation

A

Andrew

Hello All!

I'm trying to compile the following code in VS2005 Beta
class A
{
public static void SA() { }
}

class B<T> where T : A
{
public static void SB()
{
T.SA();
}
}

And I'm getting the following error
Error 7 'T' is a 'type parameter', which is not valid in the given
context

My question is: Is it a bug or feature?

Thanks in advance
 
O

Oliver Sturm

Andrew said:
I'm trying to compile the following code in VS2005 Beta
class A
{
public static void SA() { }
}

class B<T> where T : A
{
public static void SB()
{
T.SA();
}
}

And I'm getting the following error
Error 7 'T' is a 'type parameter', which is not valid in the given
context

My question is: Is it a bug or feature?

I'm quite sure it's as intended, with this reasoning: You can only call
a static method of a type you know beforehand. In your sample, you can
only call SA() on T because you know T is an A. So you could achieve the
exact same result by calling A.SA(); instead of T.SA();.

Although it looks logical at first glance, the T.SA() syntax actually
introduces an unnecessary level of complexity to the expression with no
additional benefit, I think that's why the compiler doesn't allow it.



Oliver Sturm
 
A

Andrew

I guess if I replace T.SA() with A.SA() the result will not always be
the same
Suppose I also have
class C : A
{
public static new void SA() { }
}
In this case, I want B<C>.SB() to call C.SA(), not A.SA()

What I'm trying to do is to make some sort of "static virtual" method
this way...Are there some other ways to achieve it?




Oliver Sturm пиÑал(а):
 
O

Oliver Sturm

Andrew said:
I guess if I replace T.SA() with A.SA() the result will not always be
the same
Suppose I also have
class C : A
{
public static new void SA() { }
}
In this case, I want B<C>.SB() to call C.SA(), not A.SA()

What I'm trying to do is to make some sort of "static virtual" method
this way...Are there some other ways to achieve it?

I guess that's just the point: there are no virtual static methods in
C#, and you can't trick the system this way.

In your sample, the problem is that either the method that's being
called is really the same as if you were calling A.SA(), or you are
assuming something about the derived class C that's just not true,
because there are no virtual static methods.

I remember seeing a video (a whiteboard talk or something) where Anders
gave some of the reasons for not doing virtual static methods in C#, but
I don't remember where I saw it. Maybe someone else knows a source for that?



Oliver Sturm
 
C

Christoph Nahr

What I'm trying to do is to make some sort of "static virtual" method
this way...Are there some other ways to achieve it?

Wait for Smalltalk for .NET, I suppose... as Oliver said, C# does not
have virtual statics. That's by design and I don't think it's going to
change.

If this is really important you could manually write out the various
code paths depending on the instance type of T, though:

class B<T> where T : A
{
public static void SB()
{
if (typeof(T) == typeof(A))
A.SA();
else if (typeof(T) == typeof(C))
C.SA();
}
}

Naturally, you'll lose the main advantages of polymorphism this way --
the automatic code path determination and the ability to define new
functionality in derived types.

Another option would be to use reflection to invoke the desired
member:

using System.Reflection;

class B<T> where T : A
{
public static void SB()
{
typeof(T).InvokeMember("SA",
BindingFlags.Public | BindingFlags.Static,
null, null, null);
}
}

That's nicely polymorphic, but it has the disadvantage that the method
is searched by its name whenever SB() is called, so it's quite slow.
You could make a hashtable that maps T types to buffered MethodInfo
objects for each type, though...
 
O

Oliver Sturm

Christoph said:
Another option would be to use reflection to invoke the desired
member:

using System.Reflection;

class B<T> where T : A
{
public static void SB()
{
typeof(T).InvokeMember("SA",
BindingFlags.Public | BindingFlags.Static,
null, null, null);
}
}

That's nicely polymorphic, but it has the disadvantage that the method
is searched by its name whenever SB() is called, so it's quite slow.
You could make a hashtable that maps T types to buffered MethodInfo
objects for each type, though...

And you might have to be careful to make sure that the static method is
really found. There's this thing about "flattening the hierarchy" (one
of the BindingFlags) that's sometimes needed when calling static members
by Reflection, depending on whether the type you use actually has its
own implementation of the static method or it's using the base class
one. Just a heads up.



Oliver Sturm
 

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