您不能将开放式泛型类型用作泛型类型参数,但是您可以使用特定类型S<T>
作为参数:
public static R PerformOperationOnGenericArray<T,R>
(IList<T> myList, FunctionForGenericArray<T> operation)
where R : S<T>
在您的情况下,如果类型
S
在编译时是完全定义的(闭合类型),您甚至不需要这样做:
public static S<T> PerformOperationOnGenericArray<T>
(IList<T> myList, FunctionForGenericArray<T> operation)
应该足够了。
只有在S
本身会变化时,您才需要使用第一种形式。那么我是什么意思呢?让我们看一个例子。如果您有:
class Foo<T> { }
你可以写:
public static Foo<T> PerformOperationOnGenericArray<T>
(IList<T> myList, FunctionForGenericArray<T> operation)
但是,如果您有一些相关的通用类型组:
class Foo<T> { }
class Bar<T> : Foo<T> { }
class Baz<T> : Foo<T> { }
如果您希望允许调用者指定要使用哪个,那么您需要将返回类型作为方法的泛型签名的一部分:
public static R PerformOperationOnGenericArray<T,R>
(IList<T> myList, FunctionForGenericArray<T> operation)
where R : Foo<T>
现在,调用者需要明确指定R
的类型:
PerformOperationOnGenericArray<T,Bar<T>>( ... )
如果您想允许任何接受单个参数的通用类型被允许,那么您将没有运气。类型系统无法提供表达限制的方式:
允许任何允许单个参数的泛型类型,并强制该参数为 T。
最好的方法是定义一个众所周知的接口,所有已知类型都符合(例如 IEnumerable 或自己创建的接口),并将其用作泛型约束的一部分。
public static R PerformOperationOnGenericArray<T,R>
(IList<T> myList, FunctionForGenericArray<T> operation)
where R : IEnumerable<T>
然而,在这种情况下,提供的类型必须全部实现此接口。如果您正在寻找前者(其中可以指定任何类型,只需匹配类型参数的数量),则需要使用通用的
鸭子类型(1) - C#不支持此功能。
关于这个问题有一个有趣的侧面说明。尽量避免创建无法从方法的形式参数中仅由编译器推断出类型的通用方法。当无法推断出参数时,调用者被迫指定
所有类型参数 - 这会导致混乱和冗长的代码。虽然有时确实会遇到这些情况,但在可能的情况下最好避免它们。
(1) -
C#在单个程序集中的匿名类型中支持鸭子类型,如果类型按成员的顺序、类型和名称匹配,编译器将假定它们是相同的类型。
S
是一个实际的类型。它不是一个类型参数。如果S
本身就是一个类型参数,那么你必须使用第一种形式。我会更新我的答案以使其更清晰明了。 - LBushkin