1

タイプの引数を受け入れるメソッドがありますIEnumerable(Of IEnumerable(Of 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))'

現在、.net3.5を使用しています。

これは、.net4で解決されたと聞いたList<MyObject>をIEnumerable<MyInterface>にキャストするのと同様の問題のようです。

このエラーを回避するためのアイデアはありますか?

4

1 に答える 1

2

ジェネリックインターフェイスのバリアンスサポートは.NET4まで導入されていないため、ランタイムエラーが発生します。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
于 2012-12-19T23:33:01.460 に答える