2012-12-11 82 views
1

我有接受類型的參數IEnumerable(Of IEnumerable(Of MyType))鑄造清單的IEnumerable((的的MyType)列出的)(IEnumerable的(的的MyType)的)

如果我以下的方法:

Dim list1 as new List(Of MyType) From { obj1, obj2 } 
Dim list2 as new List(Of MyType) From { obj3, obj4 } 

MyMethod({ list1, list2 }) 
它的工作原理是

如果我通過一個List(Of List(Of MyType))它編譯但給人運行時錯誤,如下:

System.InvalidCastException: Unable to cast object of type 
'System.Collections.Generic.List`1[System.Collections.Generic.List`1[MyType]]' to type 
'System.Collections.Generic.IEnumerable`1[System.Collections.Generic.IEnumerable`1[MyType]]' 

如果我通過一個MyType()()它給編譯時錯誤,如下:

Value of type '2-dimensional array of MyType' cannot be converted to 
'System.Collections.Generic.IEnumerable(Of System.Collections.Generic.IEnumerable(Of MyType))' 

我目前使用.net 3.5。

這似乎是我所聽見的.NET 4

解決任何想法,以避免這個錯誤類似於Casting List<MyObject> to IEnumerable<MyInterface>的問題嗎?

回答

2

發生的運行時錯誤,因爲通用接口方差支持沒有出臺,直到.NET 4 http://msdn.microsoft.com/en-us/library/dd233059.aspx

一些選項: 你可以升級到4(明顯)。

您可以更改MyMethod上的簽名,始終預期爲List(Of List(Of T))

您可以編寫一個擴展方法將List(Of List(Of T))轉換爲IEnumerable(Of IEnumerable(Of T))。但是,您可能要在C#程序集中執行此操作,因此您可以利用yield return。我想不出在VB.Net中處理它的好方法。

訣竅是獲取需要從List到IEnumerable的隱式轉換爲1的泛型的維數。3.5框架可以處理泛型的1維的隱式轉換,但不能像2例。下面

例子:

3.5 C#項目:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication2Helpers 
{ 
    public static class My35Extensions 
    { 
     public static IEnumerable<IEnumerable<T>> ToIEnumerableOfIEnumerable<T>(this List<List<T>> value) 
     { 
      foreach (var v1 in value) 
      { 
       yield return v1; 
      } 
     } 
    } 
} 

3.5根據您的原來的例子VB.Net項目:

Imports System.Collections.Generic 
Imports System.Linq 
Imports System.Runtime.CompilerServices 
Imports ConsoleApplication2Helpers.My35Extensions 


Module Module1 

    Sub Main() 
     Dim obj1 As New MyType, obj2 As New MyType, obj3 As New MyType, obj4 As New MyType 
     Dim list1 As New List(Of MyType) From {obj1, obj2} 
     Dim list2 As New List(Of MyType) From {obj3, obj4} 
     Dim arg1 = {list1, list2} 

     ' Works in 3.5 and 4. The non-generic array can be implicitly converted to IEnumerable. 
     ' Then the framework only has one more dimension for the second IEnumerable conversion. 
     ' The single dimension can convert implicitly in .NET 3.5 or 4. 
     MyMethod(arg1) 


     Dim arg2 As New List(Of List(Of MyType)) 
     arg2.Add(list1) 
     arg2.Add(list2) 

     ' Works in .NET 4 but NOT 3.5 because .NET Framework 4 introduces variance support for several existing generic interfaces. 
     'MyMethod(arg2) 

     ' Works in .NET 4 or 3.5. 
     ' Uses custom extension method to implicitly convert the outer List<T> to IEnumerable<T>, so we can run in .NET 3.5. 
     MyMethod(arg2.ToIEnumerableOfIEnumerable()) 

     Console.ReadKey() 
    End Sub 

    Sub MyMethod(value As IEnumerable(Of IEnumerable(Of MyType))) 
     ' 
    End Sub 

End Module 


Public Class MyType 
    Public Sub New() 

    End Sub 
End Class 
+0

感謝您的答覆。順便說一句,我真的不明白爲什麼{list1,list2}被接受。你能解釋我這種行爲嗎? – Teejay

+0

另外,你能解釋我'收益率'嗎?已經看到它,但不知道如何以及爲什麼使用它。 – Teejay

+0

我用更多的解釋和例子更新了我的答案。 – Jamey

相關問題