C#具有泛型类型的通用对象实例化

时间:2010-08-24 15:56:46

标签: c# generics dynamic

我正在研究泛型委托函数并声明List类型的返回类型。

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

我能否使用泛型返回类型而不是List,它也指定泛型类型,即S

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

我猜这是不可能的,但我看不出为什么不这样做的原因。当我指定时,编译器肯定知道类型:

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

这可能是我需要考虑使用动态类型的情况吗?

1 个答案:

答案 0 :(得分: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#支持在单个程序集中使用匿名类型进行鸭子类型输入成员 - 编译器将假定它们是相同的类型。