VB.NET: Как сравнивать разные общие списки - PullRequest
0 голосов
/ 02 марта 2011

У меня есть метод, в котором я беру универсальный объект и использую TypeOf, чтобы проверить, что было пройдено. Теперь я хотел бы передать ему List(Of T) (T - что угодно), и независимо от того, что это за T, я бы хотел сделать то же самое с этим списком. Я попробовал следующее:

public sub foo(ByVal obj As Object)
    if TypeOf obj Is List(Of Object) Then
         'do stuff
    end if
end sub

но, похоже, это не сработает, если я передам List(Of String), скажем. Я предполагаю, что List(Of Object) и List(Of String) рассматриваются как разные объекты, но я подумал, что, поскольку String является объектом, сравнение может сработать.

Теперь я понимаю, что это так же безобразно, как грех, и мне лучше перегрузить метод, чтобы принять List(Of T) в качестве его параметра, но я в основном спрашиваю из любопытства: есть ли способ сравнения типов List(Of Object1) и List(Of Object2) и получение положительного результата, так как они оба просто List(Of T)?

Ответы [ 3 ]

1 голос
/ 02 марта 2011

Чтобы проверить, относится ли объект к типу List(of T) независимо от того, к какому типу относится T, вы можете использовать Type.GetGenericTypeDefinition(), как в следующем примере:

Public Sub Foo(obj As Object)
    If IsGenericList(obj) Then
        ...
    End If
End Sub    

...

Private Function IsGenericList(ByVal obj As Object) As Boolean
    Return obj.GetType().IsGenericType _
           AndAlso _
           obj.GetType().GetGenericTypeDefinition() = GetType(List(Of ))
End Function

Или в качестве метода расширения:

Public Sub Foo(obj As Object)
    If obj.IsGenericList() Then
        ...
    End If
End Sub

...

Imports System.Runtime.CompilerServices

Public Module ObjectExtensions
    <Extension()> _
    Public Function IsGenericList(obj As Object) As Boolean
        Return obj.GetType().IsGenericType _
           AndAlso _
           obj.GetType().GetGenericTypeDefinition() = GetType(List(Of ))
    End Function
End Module
0 голосов
/ 03 марта 2011

Трудно точно сказать, чего вы пытаетесь достичь. Я очень плохо разбираюсь в чтении мыслей, поэтому я решил, что несколько других попытаются ответить на этот вопрос в первую очередь. Похоже, что их решения не были той серебряной пулей, которую вы искали, поэтому я подумал, что это удастся.

Я подозреваю, что это на самом деле синтаксис, который вы ищете:

Public Sub Foo(Of T)(ByVal myList As List(Of T))
    ' Do stuff
End Sub

Это превращает Foo в универсальный метод и гарантирует, что объект, который вы передаете в качестве аргумента (в данном случае myList), всегда является универсальным списком (List(Of T)). Вы можете вызвать любой метод, реализованный с помощью List(Of T) для параметра myList, потому что он гарантированно будет правильным типом. Там действительно не нужно ничего сложного, как Reflection.

0 голосов
/ 02 марта 2011

List(Of Object) и List(Of String) являются различными типами.Вы можете делать с ними разные вещи - например, вы не можете добавить Button к List(Of String).

. Если вы используете .NET 4, вы можете рассмотреть возможность проверки на IEnumerable(Of Object) вместо этого - тогда универсальная ковариация поможет вам.

У вас есть причина не просто сделать Foo универсальный сам по себе?

...