在泛型类型参数上调用静态方法

Rem*_*yth 99 c# generics

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


public Collection MethodThatFetchesSomething<T>()
    where T : SomeBaseClass
{
    return T.StaticMethodOnSomeBaseClassThatReturnsCollection();
}
Run Code Online (Sandbox Code Playgroud)

我得到一个编译时错误:"'T'是'类型参数',在给定的上下文中无效."

给定泛型类型参数,如何在泛型类上调用静态方法?在给定约束的情况下,静态方法必须可用.

Jar*_*Par 53

在这种情况下,您应该直接在约束类型上调用静态方法.C#(和CLR)不支持虚拟静态方法.所以:

T.StaticMethodOnSomeBaseClassThatReturnsCollection
Run Code Online (Sandbox Code Playgroud)

......可以没有什么不同:

SomeBaseClass.StaticMethodOnSomeBaseClassThatReturnsCollection
Run Code Online (Sandbox Code Playgroud)

通过泛型类型参数是不必要的间接,因此不受支持.

  • 但是如果你在子类中屏蔽了静态方法呢?public class SomeChildClass:SomeBaseClass {public new static StaticMethodOnSomeBaseClassThatReturnsCollection(){}}你能做些什么来从泛型类型访问那个静态方法吗? (23认同)
  • 查看下面的Joshua Pech的答案,我相信在那种情况下会有效. (2认同)

Jos*_*ech 26

为了详细说明以前的答案,我认为反思更接近你想要的.我可以给出你应该或不应该做某事的1001个理由,我会按照你的要求回答你的问题.我认为你应该在泛型参数的类型上调用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
}
Run Code Online (Sandbox Code Playgroud)

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

是的,我知道这是非常缓慢的,如果someParent没有强制所有的子类实现fetchAll,它可能会崩溃,但它会回答问题.

  • 如果您将硬编码方法名称替换为:`var methodeName = nameof(SomeBaseClass.StaticMethodOnSomeBaseClassThatReturnsCollection);`您可以安全地重命名方法(并获得编译器错误/使用自动重命名)。 (4认同)
  • 一点都不.JaredPar绝对正确:T.StaticMethodOnSomeBaseClassThatReturnsCollection其中T:SomeBaseClass与简单地说明SomeBaseClass.StaticMethodOnSomeBaseClassThatReturnsCollection没有什么不同. (2认同)
  • 这就是我所需要的,它可以使用静态方法 (2认同)
  • 这是我需要的答案,因为我无法控制类和基类。 (2认同)
  • @RemiDespres-Smyth 我不明白怎么做。如果 T 为静态方法实现不同的主体会怎样?StaticMethodOnSomeBaseClassThatReturnsCollection 可以是具有默认返回的静态方法的抽象类。T 可以覆盖它。那么解决方案显然非常不同。 (2认同)

小智 14

你可以做我所说的代理单例,我已经将它用作一种“静态继承”有一段时间了

interface IFoo<T> where T : IFoo<T>, new()
{
    ICollection<T> ReturnsCollection();
}

static class Foo<T> where T : IFoo<T>, new()
{
    private static readonly T value = new();
    public static ICollection<T> ReturnsCollection() => value.ReturnsCollection();
}

// Use case

public ICollection<T> DoSomething<T>() where T : IFoo<T>, new()
{
    return Foo<T>.ReturnsCollection();
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ell 7

调用这种方法的唯一方法是通过反射,但是,听起来可能将该功能包装在接口中并使用基于实例的IoC/factory/etc模式.


Bra*_*son 5

听起来你正在尝试使用泛型来解决C#中没有"虚拟静态方法"这一事实.

不幸的是,这不会奏效.

  • 如果它是静态方法,则它由基础定义和实现.在C#中没有虚拟/抽象静态方法这样的东西,也没有覆盖它.我怀疑你只是重新宣布它,这是非常不同的. (6认同)