将Object引用转换为其泛型类型

时间:2023-01-05 16:56:09

I have an Object which is really a generic with an unknown type parameter. How do I cast it into the proper generic type? For example, here's my generic:

我有一个Object,它实际上是一个带有未知类型参数的泛型。如何将其转换为正确的泛型类型?例如,这是我的通用:

Public Class MyGeneric(Of T)
    Public Property Name As String

    Public Sub New(ByVal withName As String)
        Name = withName
    End Sub
End Class

Here's what I'm trying to do:

这是我正在尝试做的事情:

Public Sub Main()
    Dim a As Object = New MyGeneric(Of String)("a")
    Dim b As Object = New MyGeneric(Of Integer)("b")
    PrintName(a)
    PrintName(b)
End Sub

Public Sub PrintName(ByVal forValue As Object)
    Dim itsType = forValue.GetType()

    If (itsType.IsGenericType() AndAlso itsType.GetGenericTypeDefinition() Is GetType(MyGeneric(Of ))) Then
        Debug.Print(DirectCast(forValue, MyGeneric(Of )).Name)
    End If
End Sub

Why does the first MyGeneric(Of ) work for a "named type" argument to GetType() but the second MyGeneric(Of ) doesn't work for a "named type" argument to DirectCast()?

为什么第一个MyGeneric(Of)适用于GetType()的“命名类型”参数但第二个MyGeneric(Of)不适用于DirectCast()的“命名类型”参数?

1 个解决方案

#1


3  

Instead of using reflection, a more reasonable design could help you. What does PrintName actually do? It prints the name of something. And that something is supposed to have a name. So why not create an interface for that?

而不是使用反射,更合理的设计可以帮助您。 PrintName实际上做了什么?它打印出某些东西的名称。那东西应该有一个名字。那么为什么不为此创建一个界面呢?

Public Interface IHasName
    Property Name As String
End Interface

... and let your generic class implement it ...

...让你的泛型类实现它......

Public Class MyGeneric(Of T)
    Implements IHasName

    Public Property Name As String Implements IHasName.Name

    '...
End Class

Then you could do:

然后你可以这样做:

Public Sub PrintName(ByVal forValue As IHasName)
    Debug.Print(forValue.Name)
End Sub

Dim a = New MyGeneric(Of String)("a")
PrintName(a)

This is much cleaner than casting an object around if you can't even be sure that it's of the correct type. Now PrintName explicitly states that it needs something with a name and the compiler can check this. You don't have to rely on the programmer to only pass valid objects.

如果你甚至不能确定它是正确的类型,那么比投射物体更清洁。现在,PrintName明确声明它需要具有名称的东西,编译器可以检查它。您不必依赖程序员只传递有效对象。

#1


3  

Instead of using reflection, a more reasonable design could help you. What does PrintName actually do? It prints the name of something. And that something is supposed to have a name. So why not create an interface for that?

而不是使用反射,更合理的设计可以帮助您。 PrintName实际上做了什么?它打印出某些东西的名称。那东西应该有一个名字。那么为什么不为此创建一个界面呢?

Public Interface IHasName
    Property Name As String
End Interface

... and let your generic class implement it ...

...让你的泛型类实现它......

Public Class MyGeneric(Of T)
    Implements IHasName

    Public Property Name As String Implements IHasName.Name

    '...
End Class

Then you could do:

然后你可以这样做:

Public Sub PrintName(ByVal forValue As IHasName)
    Debug.Print(forValue.Name)
End Sub

Dim a = New MyGeneric(Of String)("a")
PrintName(a)

This is much cleaner than casting an object around if you can't even be sure that it's of the correct type. Now PrintName explicitly states that it needs something with a name and the compiler can check this. You don't have to rely on the programmer to only pass valid objects.

如果你甚至不能确定它是正确的类型,那么比投射物体更清洁。现在,PrintName明确声明它需要具有名称的东西,编译器可以检查它。您不必依赖程序员只传递有效对象。