面白いと思ったものに出くわし、説明が欲しい.
編集
この質問は、それを修正するために何をすべきかについて回答することを意図したものではありません。私は修正を知っています。コンパイラがなぜそれを行うのかについて説明が必要です。元。このシナリオでは、プライベート関数は考慮されませんか?
問題
WhatIs というパブリック共有 (静的) 関数を持つクラスがあります。WhatIs は、オブジェクトのコレクションを持つパラメーターを受け取ります。コードはこのコレクションを繰り返し処理し、オブジェクトの型に一致するパラメーターを持つ WhatIs 関数を呼び出します。
実行すると、InvalidCastException 例外がスローされます。これは、実行が、提供された型の WhatIs 関数ではなく、これを開始した WhatIs 関数を呼び出そうとしているためです。
それは奇妙ですが、私にとって奇妙だったのは、プライベート共有機能をパブリック共有に変更すると、正常に機能することでした。
さらに奇妙なことに、オブジェクトを明示的にキャストすると、関数がプライベートであっても機能します。
何?!誰か説明してください
コード
ガッツ:
Public Class House
Public Property Furniture As ICollection(Of Object)
Public Sub New()
Furniture = New List(Of Object)
End Sub
End Class
Public Class Chair
Public Property IsComfortable As Boolean
End Class
Public Class Table
Public Seats As Integer
End Class
Public Class HouseExaminer
Public Shared Function WhatIs(thing As House) As String
Dim isA As String = "a house that contains "
For Each item In thing.Furniture
isA &= WhatIs(item)
Next
Return isA
End Function
Private Shared Function WhatIs(thing As Chair) As String
Return "a " & If(thing.IsComfortable, "comfortable", "uncomfortable") & " chair "
End Function
Private Shared Function WhatIs(thing As Table) As String
Return "a table that seats " & thing.Seats & " iguanas"
End Function
End Class
テストする
Imports System.Text
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports stuff
<TestClass()>
Public Class HouseExaminerTests
<TestMethod()>
Public Sub TestWhatIs()
Dim given As New House()
Dim expected As String
Dim actual As String
given.Furniture.Add(New Chair() With {.IsComfortable = True})
given.Furniture.Add(New Table() With {.Seats = 4})
expected = "a house that contains a comfortable chair a table that seats 4 iguanas"
actual = HouseExaminer.WhatIs(given)
Assert.Equals(expected, actual)
End Sub
End Class
結果
テストをデバッグすると、次のようになります: InvalidCastException メソッドの呼び出しが失敗しました。これは、'Public Shared Function WhatIs(thing As stuff.House) As String' をこれらの引数で呼び出すことができないためです:
引数一致パラメーター 'thing' は 'Chair' から 'House' に変換できません。
これらの変更により機能しますが、なぜですか?!
それらを公開する
HouseExaminer のプライベート共有関数をパブリックに変更し、テストを再実行します。スポイラー、それは動作します
オブジェクトを明示的にキャストする
それらをプライベートに戻してから交換します
isA &= WhatIs(item)
と
If TypeOf item Is Chair Then isA &= WhatIs(CType(item, Chair))
If TypeOf item Is Table Then isA &= WhatIs(CType(item, Table))
テストを再実行してください。