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 は、'wokka.SomeDerived' から 'wokka.ISelf(Of wokka.ISelf(Of wokka.SomeDerived))' への暗黙的な変換を許可しません」というメッセージを生成します。これは、変換があいまいであるためです。 ." Z7 から Z8 へ、または Z8 から Z9 への割り当てよりも、その割り当てがどのようにあいまいになるのでしょうか? 私が知る限り、3 つの代入はすべて表現を維持する変換でなければなりません。つまり、3 つすべてが Z7 と同じオブジェクトへの参照を単純に格納する必要があります。

SomeDerivedのインスタンスを type の参照に割り当てようとしている場合ISelf(Of ISelf(Of SomeBase))、そのインターフェイスのメンバーにアクセスしようとすると、SomeBaseまたはSomeDerived; メンバーが戻り値の型を持つメソッドである場合、TMeそのようなあいまいさがコンパイルの失敗を引き起こす可能性があることを理解できました (コンパイラーは戻り値の型が何であるかを知らないため)。ただし、割り当てが参照型変数への参照の直接ストア以外のものとして解釈できない可能性があることを考えると、「あいまいさ」のために単に参照を割り当てようとすると失敗するのはなぜですか?

ところで、意図された使用法は、 typeISelf(Of T)の読み取り専用プロパティを含めることであり、そのために予想される実装は[すべてのケースで表現を維持する変換; にクラス制約を追加する必要があったと思いますが、元の問題には影響しません]。実装に関心のあるさまざまなクラスがある場合、の共分散を利用して、他の方法では困難ないくつかのことを容易にすることができるはずです [たとえば、各クラスが実装に関心がある場合など。対応するクラス、ISelfAndLarry(Of ItsOwnType)、および/または ISelfAndCurly(Of ItsOwnType)も実装します。SelfTReturn ThisTMeISelf(Of theirOwnTypes)ISelfIMoeILarryICurlyISelfAndMoe(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 は a であることが許可されており、コンパイラーの代わりに使用できるため、どちらを意味するかわからないため、暗黙SomeBase(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)
                                                           )

しかし、最初の「方程式」からこの方程式に到達する方法は複数ありますか? 1つの方法は、もちろん共分散を使用して、最初の方程式をそれ自体に挿入することです。もう 1 つの方法は、最初の方程式ISelf(Of ...)の両辺に適用"is a"してから、何らかの推移性を使用して元の方程式と結果を結合することです。

それらが異なる方法であるかどうかは本当にわかりません。抽象的な(形式的な)数学方程式のように、ここにある種の結合性はありますか?

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

意味がわからないかもしれませんが、これは VB.NET コンパイラの単なるエラーです。例から基本クラスを削除するとどうなりますSomeBaseか? この現象は引き続き発生しますか?

VB.NET が過度に厳密であると主張されている、反変性を伴うエラーに関する別の質問があります。しかし、C# のように緩すぎるよりも、厳しすぎる方が良いかもしれません。

于 2012-12-10T21:44:35.117 に答える