Why does vb.net reject the designation of a nested covariant interface as "ambiguous",

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).

+5
covariance compiler-errors ambiguity
Dec 10 '12 at 17:20
source share
2 answers

The Strict On parameter instructs the compiler to ignore a simple link to an implicit conversion reference. This is implicit because z9 is allowed to be SomeBase(Of SomeBase(Of SomeDerived) , and since SomeDerived can be replaced with SomeBase , the compiler is not sure what you mean. But since you explicitly say in z8 that it is ISelf(of SomeDerived) , there is no speculation, I suspect that if you changed z9 to ISelf(Of SomeDerived(Of SomeDerived) , this ambiguity may disappear.

As an opinion, however, such nesting becomes very confusing as it drains by itself and can become a nightmare to maintain.

+4
Dec 10 '12 at 17:33
source share

It’s also hard for me to understand this. If it were:

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

it would be easier to imagine a lot of “routes” from SomeDerived to ISelf(Of ISelf(Of SomeBase)) .

Looking at the example question, it’s clear:

 SomeDerived "is a" ISelf(Of SomeDerived) 

by ad. From here, using covariance, you can:

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

But is there more than one way to get from the first “equation” to this? One way seems to be to insert the first equation into yourself, of course, using covariance. Another way would be the apple ISelf(Of ...) on either side of "is a" in the first equation, and then use some transitivity to combine the original equation with the result.

I'm really not sure if these are different ways. Here is some kind of associativity, as in an abstract (formal) mathematical equation:

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

Maybe I have no meaning and this is just a bug in the VB.NET compiler. What happens if you remove the SomeBase base class from the example? Is this still happening?

There is another question about contravariance errors , where he argued that VB.NET is too strict. But maybe it's better to be too strict than too loose, like C # for example.

0
Dec 10
source share



All Articles