2010-08-24 168 views
2

我正在处理泛型委托函数并声明List类型的返回类型。C#泛型类型的泛型对象实例化

public static List<T> PerformOperationOnGenericArray<T>(IList<T> myList, 
    FunctionForGenericArray<T> operation) 

我能够用一个通用的返回类型,而不是名单中也指定了一个通用型差,即s

public static S<T> PerformOperationOnGenericArray<T, S>(IList<T> myList, 
    FunctionForGenericArray<T> operation) 

我猜,这是不可能的,但我看不到的原因至于为什么不。编译器当然知道,当我指定类型:

PerformOperationOnGenericArray<int, List<string>>(myInts, i => i.Equals(12)); 

这也许是一个情况,即我需要看看使用动态类型?

回答

3

不能使用开放式泛型类型的泛型类型参数,但是,你可以使用特定类型的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>>(...) 

如果你想允许被允许接受单个参数的任何泛型类型,还有你的运气了。该型系统不提供一种方式来表达的限制:

allow any generic type that allows a single parameter, and enforce that parameter to be a T

你能做的最好的是定义一个众所周知的接口,所有已知类型的符合(如IEnumerable<T>,或者一个你手艺自己),并用其作为通用约束的一部分:

public static R PerformOperationOnGenericArray<T,R> 
      (IList<T> myList, FunctionForGenericArray<T> operation) 
    where R : IEnumerable<T> 

然而,在这种情况下,提供的类型都必须实现此接口。如果您正在寻找前者(您可以指定任何类型,只需匹配类型参数的数量),您正在寻找通用的duck typing(1) - C#不支持。

有关这方面的一个有趣的方面说明。创建一个通用方法,其类型不能由编译器仅从方法的形式参数中推断出来,这是要尽量避免的。当无法推断参数时,呼叫者被强制指定所有类型参数 - 这会导致混淆和冗长的代码。尽管有时候这些情况确实会出现,但如果可能的话,最好尽量避免它们。

(1) - C#确实支持单个组件内的匿名类型鸭打字如果类型的顺序,类型和它们的成员的名称相匹配 - 在其上的编译器将假定它们是相同的类型。

+0

感谢您的回复。不幸的是我已经尝试了你的第二个建议,编译器不喜欢S.我得到“Unknown Entity'S'” – 2010-08-24 16:08:50

+0

@Ryan - 第二种形式要求'S'是一个实际的类型。它不是一个类型参数。如果'S'本身就是一个类型参数,那么你**必须使用第一种形式。我会更新我的答案,使其更清楚。 – LBushkin 2010-08-24 16:11:47

+0

啊..我错了你在说什么。现在有意义了,谢谢你的澄清。 这不是要生产的东西。只需查看委托函数的泛型类型的界限即可。 – 2010-08-24 16:17:47