In code:
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
Assigning directly from Z7 to Z9 gives the message "Error 13 Option Strict On" does not allow implicit conversions from "wokka.SomeDerived" to "wokka.ISelf" (from wokka.ISelf (Of wokka.SomeDerived)) "because the conversion is ambiguous" . How is this appointment more ambiguous than from Z7 to Z8, or from Z8 to Z9? As far as I can tell, all three assignments should be transformations that preserve the view, which means that all three should just store a reference to the same object as Z7.
I could understand that if I were trying to assign an instance of SomeDerived to a link like ISelf(Of ISelf(Of SomeBase)) , trying to access a member of this interface could lead to an implementation from SomeBase or SomeDerived ; if the element was a method with a return type of TMe , I could understand that such an ambiguity could lead to compilation failure (since the compiler did not know what the return type would be). However, I am puzzled why it’s not possible to simply try to assign the link because of the “ambiguity”, given that the assignment cannot be interpreted as anything other than direct storage of the link to the variable of the reference type?
BTW, the intended use would be for ISelf(Of T) contain a read-only Self property of type T , for which the expected implementation would be Return This [conversion preserving the view in each case; I suppose I should have added a class constraint on TMe , but that does not affect the original problem]. If there are many classes that are interested in implementing ISelf(Of theirOwnTypes) , it should be possible to use ISelf covariance to facilitate some things that would otherwise be difficult (for example, if each class is interested in implementing IMoe , ILarry and / or ICurly , etc. also implements the corresponding classes ISelfAndMoe(Of ItsOwnType) , ISelfAndLarry (Of ItsOwnType) and / or ISelfAndCurly (Of ItsOwnType) , etc. then one can accept a parameter type which is known to implement any combination of those interfaces eg ISelfAndMoe (Of ISelfAndLarry (Of ICurly)) param . Given that declaration, param would implement IMoe , and param.Self would implement ILarry , and param.Self.Self would implement would implement ICurly . Further, if the class implements the expected pattern, one could cast param to eg ISelfAndCurly (From IMoe) , if one wanted to call a routine which needed those two interfaces but didn't need ILarry` (such a launch may fail if the implementation did something unexpected, but should succeed if the class of the object follows the expected pattern).
supercat Dec 10 '12 at 17:20 2012-12-10 17:20
source share