5

在代码中:

Interface ISelf(Of Out TMe)
End Interface
Class SomeBase
    Implements ISelf(Of SomeBase)
End Class
Class SomeDerived
    Inherits SomeBase
    Implements ISelf(Of SomeDerived)
End Class
Module ISelfTester
    Sub TestISelf()
        Dim z7 As New SomeDerived
        Dim z8 As ISelf(Of SomeDerived)
        Dim z9 As ISelf(Of ISelf(Of SomeDerived))
        z8 = z7
        z9 = z8
        z9 = z7 ' Why is this illegal?
    End Sub
End Module

直接从 Z7 到 Z9 的分配产生消息“错误 13 Option Strict On 不允许从 'wo​​kka.SomeDerived' 到 'wokka.ISelf(Of wokka.ISelf(Of wokka.SomeDerived))' 的隐式转换,因为转换不明确。” 与从 Z7 到 Z8 或从 Z8 到 Z9 的分配相比,该分配如何更加模棱两可?据我所知,所有三个分配都必须是保留表示的转换,这意味着所有三个必须简单地存储对与 Z7 相同的对象的引用。

我可以理解,如果我试图将 的实例分配给SomeDerivedtype 的引用ISelf(Of ISelf(Of SomeBase)),则尝试访问该接口的成员可能会从SomeBaseor中产生实现SomeDerived;如果成员是返回类型的方法TMe,我可以理解这种歧义可能导致编译失败(因为编译器不知道返回类型是什么)。不过,我很困惑,为什么仅仅尝试分配引用会因为“歧义”而失败,因为分配不可能被解释为除了对引用类型变量的引用的直接存储之外的任何东西?

顺便说一句,预期的用途是ISelf(Of T)包含一个只读属性Selftype T,预期的实现将是Return This[在每种情况下都保留表示形式的转换;我想我应该在 中添加一个类约束TMe,但它不会影响原始问题]。如果有多种类都对实现感兴趣ISelf(Of theirOwnTypes),那么应该可以利用 的协方差ISelf来促进一些原本会很困难的事情[例如,如果每个类都对实现IMoeILarry和/或ICurly等感兴趣。还实现了相应的类ISelfAndMoe(Of ItsOwnType)ISelfAndLarry(Of ItsOwnType) 和/或 ISelfAndCurly(Of ItsOwnType), etc. then one can accept a parameter type which is known to implement any combination of those interfaces e.g.ISelfAndMoe(Of ISelfAndLarry(Of ICurly)) param . Given that declaration,param would implementIMoe , andparam.Self would implementILarry , andparam.Self.Self would implementICurly . Further, if the class implements the expected pattern, one could castparam to e.g.ISelfAndCurly(Of IMoe) , if one wanted to call a routine which needed those two interfaces but didn't needILarry`(如果实现做了一些意想不到的事情,这种转换可能会失败,但如果对象的类如下则应该成功预期的模式)。

4

2 回答 2

4

Option Strict On 告诉编译器忽略对引用隐式转换的简单引用。它是隐含的,因为 z9 被允许是 aSomeBase(Of SomeBase(Of SomeDerived)并且因为SomeDerived可以替换SomeBase编译器不确定你的意思是哪个。但是因为您在 z8 中明确表示ISelf(of SomeDerived)没有任何猜测。我怀疑如果您将 z9 更改为ISelf(Of SomeDerived(Of SomeDerived)这种歧义可能会消失。

然而,作为一种观点,这种嵌套会变得非常混乱,因为它会叠加在自身上,并且可能成为维护的噩梦。

于 2012-12-10T17:33:18.563 回答
0

我也觉得这很难理解。如果是这样的话:

Dim y9 As ISelf(Of ISelf(Of SomeBase))
y9 = z7

SomeDerived想象从到 的许多“路线”会更容易ISelf(Of ISelf(Of SomeBase))

看问题的例子,很明显:

SomeDerived "is a" ISelf(Of SomeDerived)

通过声明。从这里,使用协方差,可以:

ISelf(Of SomeDerived) "is a" ISelf(Of
                                      ISelf(Of SomeDerived)
                                                           )

但是从第一个“方程”到这个方程有不止一种方法吗?一种方法似乎是将第一个方程插入自身,当然使用协方差。另一种方法可能是在第一个方程ISelf(Of ...)的两边加上苹果"is a",然后使用某种传递性将原始方程与结果结合起来。

我真的不确定这些是否是不同的方式。这里是否存在某种关联性,就像在抽象(正式)数学方程中一样:

(a·a)*x  =  a*(a*x)

也许我没有意义,这只是VB.NET编译器中的一个错误。如果SomeBase从示例中删除基类会发生什么?这种行为是否仍然存在?

还有一个关于逆变错误的问题,它声称 VB.NET 过于严格。但也许过于严格比C# 看起来的过于宽松要好。

于 2012-12-10T21:44:35.117 回答