2

在 VB 中比较类型时,以下内容按预期工作,并使当前实例能够与特定继承的类进行比较,在这种情况下返回(来自LINQPadFalse的片段)

Sub Main
    Dim a As New MyOtherChildClass

    a.IsType().Dump()
End Sub

' Define other methods and classes here
MustInherit class MyBaseClass
    Public Function IsType() As Boolean
        Return TypeOf Me Is MyChildClass
    End Function
End Class

Class MyChildClass 
    Inherits MyBaseClass
End Class

Class MyOtherChildClass
    Inherits MyBaseClass
End Class

但是,当引入泛型时,VB 编译器失败并出现错误Expression of type 'UserQuery.MyBaseClass(Of T)' can never be of type 'UserQuery.MyChildClass'.

' Define other methods and classes here
MustInherit class MyBaseClass(Of T)
    Public Function IsType() As Boolean
        Return TypeOf Me Is MyChildClass
    End Function
End Class

Class MyChildClass 
    Inherits MyBaseClass(Of String)
End Class

Class MyOtherChildClass
    Inherits MyBaseClass(Of String)
End Class

C#中的等效代码编译并允许比较,返回正确的结果

void Main()
{
    var a = new MyOtherChildClass();

    a.IsType().Dump();
}

// Define other methods and classes here

abstract class MyBaseClass<T>
{
    public bool IsType()
    {
        return this is MyChildClass;
    }
}

class MyChildClass : MyBaseClass<string>
{
}

class MyOtherChildClass : MyBaseClass<string>
{
}

为什么VB编译器不允许这种比较?

4

2 回答 2

2

您提出了一个关于 VB/C# 编译的有趣观点,我无法真正谈论。如果您正在寻找解决方案,这里有一种方法可以从问题如何识别泛型类?

定义这些函数:

Public Function IsSubclassOf(ByVal childType As Type, ByVal parentType As Type) As Boolean
    Dim isParentGeneric As Boolean = parentType.IsGenericType

    Return IsSubclassOf(childType, parentType, isParentGeneric)
End Function

Private Function IsSubclassOf(ByVal childType As Type, ByVal parentType As Type, ByVal isParentGeneric As Boolean) As Boolean
    If childType Is Nothing Then
        Return False
    End If

    If isParentGeneric AndAlso childType.IsGenericType Then
        childType = childType.GetGenericTypeDefinition()
    End If

    If childType Is parentType Then
        Return True
    End If

    Return IsSubclassOf(childType.BaseType, parentType, isParentGeneric)
End Function

像这样调用:

Dim baseType As Type = GetType(MyBaseClass(Of ))
Dim childType As Type = GetType(MyOtherChildClass)

Console.WriteLine(IsSubclassOf(childType, baseType))
'Writes: True

这是一个Microsoft Connect Ticket,它可能会处理此问题,并解释这是通用类型的功能还是错误。

Type Of尽管说明对于类的文档似乎不支持这种情况,但在以下情况下typeof 将返回 true:

objectexpressiontypename类型或继承typename

于 2013-08-15T04:34:23.550 回答
0

我对 C# 很熟悉,但对 VB 不太熟悉。但是,示例 VB 代码和示例 C# 代码似乎不同。在您使用的 VB 示例Return TypeOf Me Is MyChildClass中,在 C# 中为return typeof(this) is MyChildClass;. 但是(据说可以工作的)C# 示例只有return this is MyChildClass;.

我希望这TypeOf Me Is MyChildClass是询问左侧的实例表达式(即 a Type)是否可以分配给声明为右侧(MyChildClass)类型的变量。由于框架类Type与您没有任何联系,MyChildClass因此这是不可能的,因此编译器可以通过警告或错误捕捉到一个可能的错误——可能是您得到的错误。

相反,我认为 VB 代码应该Return Me Is MyChildClass与 C# 示例匹配,该示例应该正确询问是否可以将实例 Me 分配给声明为MyChildClass. 如果使用此语法,VB 是否仍然反对,或者是否可以修复错误并获得正确的行为?

于 2017-05-22T23:24:51.533 回答