【问题标题】:Is it possible to use IList(Of IList(Of String))?是否可以使用 IList(Of IList(Of String))?
【发布时间】:2011-08-02 18:42:05
【问题描述】:

我正在尝试使用一个变量,它只是一个字符串列表的列表。 我已经声明如下:

Dim iRows As New List(Of List(Of String))

然后我尝试将它作为参数传递给另一个方法,我已将方法定义如下:

Public Sub Import(ByVal Rows As IList(Of IList(Of String)))
    For Each Row As IList(Of String) In Rows
        ImportRow(Row)
    Next
End Sub

不幸的是,当我尝试运行该代码时,我收到以下错误,它试图将我的变量传递给我的方法。

System.InvalidCastException 未被用户代码处理 Message="无法将类型为“System.Collections.Generic.List1[System.Collections.Generic.List1[System.String]]”的对象转换为类型“System.Collections.Generic.IList1[System.Collections.Generic.IList1[System.String]]”。 "

当我将方法定义更改为使用类型而不是接口时,它可以工作。

Public Sub Import(ByVal Rows As List(Of List(Of String)))
    For Each Row As IList(Of String) In Rows
        ImportRow(Row)
    Next
End Sub

那么,以这种方式使用泛型与接口是不可能的?只要我不嵌套它们,它就可以正常工作。

【问题讨论】:

    标签: vb.net string list generics interface


    【解决方案1】:

    是的,可以创建IList(Of IList(Of String)) - 但List(Of (List(Of String)) 不是。考虑到在后一种情况下,您可以调用

    listOfLists.Add(arrayOfStrings)
    

    作为字符串数组实现IList(Of String)

    基本上这与考虑IList(Of Fruit)List(Of Banana) 完全相同 - 一堆香蕉不是水果碗,因为你不能在其中添加一个苹果。

    在您的情况下,您需要创建一个List(Of IList(Of String)) - 声明一个IList(Of List(Of String))

    现在有趣的是,您可以在 .NET 4 中使用 List(Of List(Of String)) 作为 IEnumerable(Of IEnumerable(Of String)),因为 通用协变和逆变 - IEnumerable(Of T) 在 @ 中是协变的987654333@。但是,IList(Of T)不变的

    泛型协变和逆变是一个棘手的话题。 Eric Lippert 有written a great deal about it - 使用 C# 作为语言而不是 VB,但希望你仍然可以理解它。

    【讨论】:

    • 现在一切都说得通了。谢谢。
    • 微软没有为 IList 实现 IReadableList 基类型真是太糟糕了,因为期望 IReadableList(Of Fruit) 的代码可以使用 IReadableList(Of Apple)。不过,在不破坏现有代码的情况下,现在可能需要一些非常讨厌的运行时黑客来实现这样的东西。
    • @supercat:是的——它会很有用。这很棘手 - 接口分解过多会导致混乱,但过少会导致这种事情:(
    • @Jon Skeet:我真的不喜欢那些强烈期望许多实现不能处理所有成员的接口。 IEnumerable.Reset 简直丑陋。想象一下,如果有一个 IMultipassEnumerable,它继承了 IEnumerable,包括 Reset,并保证使用相同枚举器的多次传递将产生相同的数据;可以削弱 IEnumerable 的“合同”,以指定如果在枚举期间更改集合,则枚举器可以返回“合理”数据或引发异常; ILiveEnumerable 将继承 IEnumerable 但...
    • ...指定即使修改了集合(而不是抛出异常),它也应该返回合理的数据,并且 IPurgeableEnumerable 将提供 PurgeForAll 方法,该方法将调用每个元素上的函数并删除函数返回 true 的所有项目(一种经常需要的模式,但如果没有枚举器的支持则很难实现)。
    【解决方案2】:

    首先像这样声明 iRows:

    Dim iRows As New List(Of IList(Of String))
    

    然后,当您将new List(Of String) 添加到iRows 时,它将适当地隐式转换。

    【讨论】:

    • 您的回答正是我所需要的。乔恩只是解释了更多。感谢您的帮助。
    【解决方案3】:

    尝试以下更改:

    Public Sub Import(ByVal Rows As List(Of List(Of String)))
        For Each Row As List(Of String) In Rows
            ImportRow(Row)
        Next
    End Sub
    

    似乎不需要从List 转换为IList

    【讨论】:

    • 感谢您的热情,但这与@Telarian 的要求相差甚远。
    猜你喜欢
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 2016-05-21
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多