在genericstypes参数上调用静态方法

我希望能做这样的事情,但在C#中似乎是非法的:

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

我得到一个编译时错误:“'T'是'types参数',在给定的上下文无效。

给定一个genericstypes参数,如何在generics类上调用静态方法? 给定约束,静态方法必须可用。

在这种情况下,您应该直接调用约束types的静态方法。 C#(和CLR)不支持虚拟静态方法。 所以T.StaticMethodOnSomeBaseClassThatReturnsCollection可以和SomeBaseClass.StaticMethodOnSomeBaseClassThatReturnsCollection没有什么不同。 通过genericstypes参数是不必要的间接,因此不支持。

为了详细说明以前的答案,我认为反思更接近你想要的东西。 我可以给你1001个理由说明为什么你应该或不应该做什么,我只是回答你的问题。 我想你应该调用通用参数的types的GetMethod方法,并从那里去。 例如,对于一个函数:

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

其中T是具有静态方法fetchAll()的任何类。

是的,我知道这是非常缓慢的,如果一些父类不强制所有的子类实现fetchAll,但它会按照问题回答问题。

调用这种方法的唯一方法是通过reflection,但是,听起来好像有可能将这个function封装在一个接口中,并使用基于实例的IoC /工厂/ etc模式。

这听起来像你正在试图使用generics来解决在C#中没有“虚拟静态方法”的事实。

不幸的是,这不会奏效。

在这里,我发表了一个工作的例子,这是一个解决方法

 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(); } 

截至目前,你不能。 你需要一种告诉编译器T有这种方法的方式,目前没有办法做到这一点。 (许多公司正在推动微软扩大在一般约束条件下可能被指定的内容,所以未来可能会这样做)。

你应该能够使用reflection来做到这一点,正如这里所描述的那样

我只是想把它扔在那里,有时代表根据上下文来解决这些问题。

如果需要将静态方法作为某种工厂或初始化方法调用,那么可以声明一个委托并将静态方法传递给相关的generics工厂,或者无论它需要使用此静态方法的generics类。

例如:

 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(); } } 

不幸的是,你不能强制类有正确的方法,但你至less可以编译时强制生成的工厂方法具有它所期望的一切(即一个具有正确签名的初始化方法)。 这比运行时reflectionexception更好。

这种方法也有一些好处,比如你可以重用init方法,让它们成为实例方法等等。