【问题标题】:Generic Types and overriding泛型类型和覆盖
【发布时间】:2012-09-09 00:50:09
【问题描述】:

我有一个类,我想用这些定义实现一个函数 Import:

1. Public Sub Import(of T)(ByRef Data() as T)

2. Public Sub Import(of T)(ByRef Data(,) as T)

3. Public Sub Import(of T)(ByRef Data()() as T)

4. Public Sub Import(of T)(ByRef Data as List(Of T))

5. Public Sub Import(of T)(ByRef Data as List(Of T()))

6. Public Sub Import(of T)(ByRef Data as List(Of List(Of T)))

7. Public Sub Import(of T)(ByRef Data() as List(Of T))

我的问题是编译器在我编写时无法确定正确的导入函数:

Dim ArrayList as List(of String)() = something
MyClass.Import(ArrayList)

我明白为什么,因为 1 和 7 可以代表同一个东西。

所以我尝试在课堂上写作:

Public Sub Import(Of T)(ByRef Data() As T)
    Try
        Select Case True
            Case Data(0).GetType().IsArray
                ImportArrayArrayT(Data)
            Case Data(0).GetType.IsGenericType
                ImportArrayListT(Data)
            Case Else
                ImportArrayT(Data)
        End Select
    Catch ex As Exception

    End Try
End Sub

Protected Sub ImportArrayT(Of T)(ByRef Data() As T)
End Sub

Protected Sub ImportArrayArrayT(Of T)(ByRef Data As T()())
End Sub

Protected Sub ImportArrayListT(Of T)(ByRef Data() As List(Of T))
End Sub

但我在ImportArrayArrayT(Data)ImportArrayListT(Data)ImportArrayT(Data) 上遇到另一个错误。消息错误表示无法从方法的参数中推断出数据的类型。

我需要使用泛型类型,因为我不在乎类型是 String、Integer、Double...但如果它是 Array、List 或它们的组合(最大二维),我需要不同的代码。

那么您有什么想法可以解决我的问题吗?我不会为每个类型(字符串、整数、...)以及列表和数组的组合编写导入函数。

谢谢

【问题讨论】:

  • 好像导入列表和导入单个元素是不同的操作,应该有不同的函数名。您还可以使用IEnumerable<T>IList<T> 等接口来减少需要处理的类型数量。

标签: .net arrays list generics


【解决方案1】:

我要提出的一个警告是不要过度考虑管道。

如果您知道如何为您可以支持的特定类型执行导入,请考虑为您的导入声明一个接口,然后让具体类实现可以处理您的转换的类型,然后将接口类型作为您的参数函数,例如 IImportable(例如)。

编辑:更多说明

使用 IImportable 之类的接口,您可以将这些 Import def 减少到:

Protected Sub Import(of T)(ByRef IImportable(Of T))

您甚至可以编写一个抽象基类来实现接口,然后为您希望能够从中导入的每种类型编写具体实现。

只是一个想法...希望它有用。

【讨论】:

    【解决方案2】:

    当编译器无法推断出参数的类型时,你必须给它一点提示。试试这个:

    将 ArrayList 调暗为列表(字符串)() Module1.Import(列表(字符串))(ArrayList)

    【讨论】:

    • 这可能是一个解决方案,但如果可能的话,我希望用户不必明确指定类型。不过,我正在寻找你所说的,所以谢谢。
    【解决方案3】:

    感谢您的回答,但我想我已经找到了使用 ParamArray 的解决方案(夜晚是一个很好的帮助!)。如果我使用这段代码,它看起来不错:

    Public Sub Import(Of T)(ByVal ParamArray Data As List(Of T)())
    End Sub
    
    Public Sub Import(Of T)(ByVal ParamArray Data()() As T)
    End Sub
    
    Public Sub Import(Of T)(ByRef Data(,) As T)
    End Sub
    
    Public Sub Import(Of T)(ByRef Data As List(Of List(Of T)))
    End Sub
    
    Public Sub Import(Of T)(ByRef Data As List(Of T()))
    End Sub
    

    如果我不想区分一维和二维数组(或列表),编译器会在所有情况下找到正确的函数。如果它是 2D 或 1D 数据,我想我可以管理它。

    我会在结束这个话题之前测试更多的东西,但目前还可以。

    【讨论】:

    • 如果 ParamArray 简化了重载解决方案,我会感到惊讶,因为您仍然可以像没有 ParamArray 的情况下一样调用该方法,但是您可以获得其他方法来调用它,我希望这样做更模棱两可。您确定它在这些情况下调用了您预期的重载吗?
    • 我也很惊讶,但是使用 ParamArray,我可以将一维或二维数组(或列表)放入同一个函数中,我认为这是我之前的问题。现在无论 T,所有 Import 函数都不同,所以编译器很高兴(我也很高兴!)。
    【解决方案4】:

    您可以更改(至少)其中一个重载的名称,以类似于 IList 接口上的 Add 和 AddRange 的方式命名它们。除非您使用反射或动态语言功能,否则选择调用哪个方法将是编译时决定。您的方法调用代码每次都将始终引用一个特定的重载,而不仅仅是 Import,即使在您编写该代码时可能会觉得这是一个动态选择,因为您只需编写 Import 而无需考虑您是哪一个想用。它不像类继承,在编译后可以根据每个实例的类型继承基类型的方式来更改方法的最终选择。因此,您也可以只更改导致冲突的方法的名称。

    如果您的目标是动态使用,您最好拥有一个接受对象参数的Import 方法,然后对该对象实施您自己的类型检查,以决定将哪些现有方法用于导入,因此,当输入实例的解释不明确时,您可以决定自己的偏好顺序。然后,您可以使用任何输入(甚至在运行时)调用您的方法,并让它选择您喜欢的导入方法。我似乎记得,当.NET2 中引入泛型时,typeof 关键字的效率要高得多,因此它可能不像您最初认为的那样糟糕,因为至少避免了一些泛型.

    有关 typeof 的用法,请参阅http://msdn.microsoft.com/en-us/library/0ec5kw18(v=vs.80).aspx。代码看起来像:

    If (input Is TypeOf(List(Of T)))
        ' Import somehow'
    
    Else If (input Is TypeOf(ArrayList(Of T)))
        ' Import some other way'
    
    ' etc.'
    End If
    

    【讨论】:

    • 你说的很有趣,我已经尝试过这样做(我的帖子的第二部分),但是:(1)我有一个问题,以及(2)当我使用一个对象参数,如果我使用TheObject.GetType(),它会给我对象而不是列表(字符串)。而且,似乎很难知道一个对象何时是一个列表,对于数组来说没问题GetType.IsArray,对于列表我用过GetType.IsGenericType,但事实并非如此。所以如果你有一个例子来管理它,它应该很好!
    • 在上面的编辑中尝试 TypeOf...我可能没有 100% 获得代码示例,但我已经链接到它的文档。
    • 对不起,我虽然 TypeOf 是 C# 编写的 GetType。但是,我不确定是否理解您的示例。你写的可以包含在这个函数Public Sub Import(of T)(input as object)中,但是在这种情况下什么是T?
    • T 将是包装在任何正在使用的集合构造中的对象的最终类型。泛型类型参数不必在方法参数中使用 - 可以通过说 Import(Of T)(myObject) 来调用该方法。
    • 好的,我虽然该程序使用方法参数确定 T。我会尝试你的解决方案,它似乎非常好。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 2020-03-14
    • 2012-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多