嵌套泛型类型参数 - 如何处理?

时间:2010-02-22 16:51:22

标签: c# generics

我在参数声明中创建了一些使用嵌套类型参数泛型类型的方法:

public void Foo(IList<Pair<double, IList<double>>> myParameter)
{ // code goes here 
}

我想要实现的是强制此方法接受4种类型的变量:

  • List<Pair<double, List<double>>> myVar
  • List<Pair<double, double[]>> myVar
  • Pair<double, List<double>>[] myVar
  • Pair<double, double[]>[] myVar

但似乎第二个嵌套接口无法通过C#即时转换。在尝试将上面列出的一些变量传递给我的方法时,我收到错误:

  

参数1:无法从System.Collections.Generic.List&lt; ...&gt;转换无法从System.Collections.Generic.IList&lt; ...&gt;转换

我真的需要为此方法创建两个别名来处理此问题吗?或者也许我可以使用某种技巧来克服这个问题?

3 个答案:

答案 0 :(得分:5)

您的代码会导致出现差异问题。

内部IList<double>允许您指定List<double>,即使您最初通过了double[],也会破坏类型安全。

(出现这种情况的原因与List<Orange>可能不会被视为List<Fruit>:您可以将苹果推入其中。)

为了实现正确的方差行为,您必须通过使用IEnumerable<T>而不是IList<T>来确保不变性(仅适用于.NET 4.0)。

以前版本的C#根本无法处理差异!

答案 1 :(得分:2)

您可以在C#2.0 +

中使用通用约束
void Foo<TList>(IList<Pair<double, TList>> myParameter)
   where TList : IList<double>

C#在这个类型推断上有问题,所以你需要在调用期间指定。

答案 2 :(得分:1)

不知道你传递的是什么,这里的问题很可能是因为你没有variance on generic type parameters

幸运的是,在C#4.0中,这是存在的,我愿意猜测你可以使用IEnumerable<double>作为内部类型参数,它会起作用(除非你需要改变列表而不是只是迭代它。

如果您无法使用C#4.0,那么您将不得不将List<T>变量的类型参数更改为所请求的特定类型。