Call a static method for a generic parameter type

I was hoping to do something like this, but in C # it looks illegal:

public Collection MethodThatFetchesSomething<T>() where T : SomeBaseClass { return T.StaticMethodOnSomeBaseClassThatReturnsCollection(); } 

I get a compile-time error: "'T' is a type parameter that is not valid in this context.

Given the generic type parameter, how can I call a static method for a generic class? The static method must be available subject to restrictions.

+82
generics c #
Oct 13 '08 at 3:49
source share
8 answers

In this case, you just need to call the static method on the limited type directly. C # (and CLR) do not support virtual static methods. So:

 T.StaticMethodOnSomeBaseClassThatReturnsCollection 

... may not differ:

 SomeBaseClass.StaticMethodOnSomeBaseClassThatReturnsCollection 

Passing a generic type parameter is unnecessary indirect and therefore not supported.

+47
Oct 13 '08 at 8:08
source share

To clarify the previous answer, I think thinking is closer to what you want here. I could give 1001 reasons why you should or should not do something, I will simply answer your question as asked. I think you should call the GetMethod method on the type of the general parameter and go from there. For example, for a function:

 public void doSomething<T>() where T : someParent { List<T> items=(List<T>)typeof(T).GetMethod("fetchAll").Invoke(null,new object[]{}); //do something with items } 

Where T is any class that has a static fetchAll () method.

Yes, I know that it is terribly slow and it may crash if someParent does not force all its child classes to implement fetchAll, but it answers the question asked.

+18
Dec 02 '11 at 15:31
source share

The only way to call such a method is through reflection. However, it seems that one could wrap this functionality in an interface and use the instance-based IoC / factory / etc template.

+7
Oct 13 '08 at 4:06
source share

It sounds like you're trying to use generics to get around the fact that there are no "virtual static methods" in C #.

Unfortunately this will not work.

+4
Oct 13 '08 at 3:56
source share

You cannot at the moment. You need to tell the compiler that T has this method, and there is currently no way to do this. (Many are pushing Microsoft to expand on what might be stated in the general restriction, so perhaps this will be possible in the future).

+2
Oct 13 '08 at 3:53
source share

Here I am writing an example that works, this is a workaround

 public interface eInterface { void MethodOnSomeBaseClassThatReturnsCollection(); } public T:SomeBaseClass, eInterface { public void MethodOnSomeBaseClassThatReturnsCollection() { StaticMethodOnSomeBaseClassThatReturnsCollection() } } public Collection MethodThatFetchesSomething<T>() where T : SomeBaseClass, eInterface { return ((eInterface)(new T()).StaticMethodOnSomeBaseClassThatReturnsCollection(); } 
+2
Jan 20 '09 at 16:54
source share

You should be able to do this using reflection, as described here.

+1
Feb 13 2018-11-11T00:
source share

I just wanted to throw it there, that sometimes delegates solve these problems, depending on the context.

If you need to call the static method as a kind of factory or initialization method, then you can declare the delegate and pass the static method to the corresponding universal factory or what it needs is a "common class using this static method".

For example:

 class Factory<TProduct> where TProduct : new() { public delegate void ProductInitializationMethod(TProduct newProduct); private ProductInitializationMethod m_ProductInitializationMethod; public Factory(ProductInitializationMethod p_ProductInitializationMethod) { m_ProductInitializationMethod = p_ProductInitializationMethod; } public TProduct CreateProduct() { var prod = new TProduct(); m_ProductInitializationMethod(prod); return prod; } } class ProductA { public static void InitializeProduct(ProductA newProduct) { // .. Do something with a new ProductA } } class ProductB { public static void InitializeProduct(ProductB newProduct) { // .. Do something with a new ProductA } } class GenericAndDelegateTest { public static void Main() { var factoryA = new Factory<ProductA>(ProductA.InitializeProduct); var factoryB = new Factory<ProductB>(ProductB.InitializeProduct); ProductA prodA = factoryA.CreateProduct(); ProductB prodB = factoryB.CreateProduct(); } } 

Unfortunately, you cannot ensure that the class has the correct method, but you can at least compile the time so that the resulting factory method has everything it expects (i.e., an initialization method with a precisely matched signature). This is better than eliminating run-time reflection.

This approach also has some advantages, i.e. you can reuse init methods, use them as instance methods, etc.

+1
Dec 28 '11 at 15:08
source share



All Articles