On Fri, 19 Sep 2008 09:27:25 -0700, Filip Zawada <fz*****@gmail.comwrote:
[...]
The question is why can't I call a static method using generic
parameter?
I've specified that T is of type GoodBase<T>, so static methods from
GoodBase should be available by using generic parameter... Isn't
GoodBase<SomeEntity>.Met() actually the same as T.Met()? Why do I have
to repeat myself?
You don't. But, you also can't use T directly as the type.
It doesn't make sense to call static members on the type parameter. This
is true regardless of whether or not the type parameter inherits a generic
type or a non-generic one. Consider:
class A
{
public static void MethodA() { }
}
class B<T: where T : A
{
public void MethodB()
{
T.MethodA();
}
}
One of two possible behaviors may be expected here.
First, it may be expected that if the class T reimplements MethodA(), you
want the implementation in the most-derived class to be called. That is,
if T is not A and has its own implementation of MethodA, you want _that_
implementation to be called rather than A.MethodA.
If this is the case, then it's not possible for the compiler to fulfill
your intent, because it needs to know when it compiles the _generic_ class
how to get at the method, and at that point the type parameter hasn't
actually been resolved yet.
I suppose in theory, the compiler could generate some complex code to use
reflection to determine at run-time the correct static method to call.
But that could lead to a serious, non-obvious performance problem at best,
and at worst could cause some subtle, hard-to-find bugs. It's wise for
the language design to prohibit the use of a type parameter in that
context.
Of course, there's nothing stopping you from writing such code
explicitly. But in that case, it would be obvious looking at the code
that's what you're doing.
Alternatively, maybe you always want to call A.MethodA. If that's the
intent of the code, then you can get it to work by doing exactly that:
class B<T: where T : A
{
public void MethodB()
{
A.MethodA();
}
}
Note that if T inherits a generic type, then you can use the same
technique, supplying the type parameter:
class A<T>
{
public static void MethodA() { }
}
class B<T: where T : A<T>
{
public void MethodB()
{
A<T>.MethodA();
}
}
In your own example, it would look like this:
public class DictModel<T>
: IDictModel<T>
where T : GoodBase<T>
{
public void Test()
{
GoodBase<SomeEntity>.Met(); //OK
SomeEntity.Met(); //OK
GoodBase<T>.Met(); //OK
}
}
That ensures that if the Met() method depends on the type parameter, that
you actually get the implementation you desire (as opposed to calling
GoodBase<SomeEntity>() in a class where you don't actually know that the
type parameter T is "SomeEntity", which would be wrong).
Hope that helps.
Pete