Strange issue with .Net inheritance and element visibility

I have a problem in the VB.Net class library, which I greatly simplified to the next ...

Public MustInherit Class TargetBase

End Class

Public Class TargetOne
    Inherits TargetBase
End Class

Public Class TargetTwo
    Inherits TargetBase
End Class

Public Class TargetManager
    Public Sub UpdateTargets(ByVal Targets As List(Of TargetBase))
        For Each objTarget As TargetBase In Targets
            UpdateTarget(objTarget)
        Next
    End Sub

    Private Sub UpdateTarget(ByVal Value As TargetOne)

    End Sub

    Private Sub UpdateTarget(ByVal Value As TargetTwo)

    End Sub
End Class

This will not be compiled due to a syntax error in the string UpdateTarget(objTarget). Overload resolution error because the available "UpdateTarget" cannot be called without narrowing the conversion.

So, I changed the For-Each loop to use Object instead of TargetBase ...

For Each objTarget As Object In Targets
    UpdateTarget(objTarget)
Next

Now it compiles, but I get a runtime error. Public element UpdateTarget on type "TargetManager" not found.

So, I took the next step by making 2 UpdateTarget () an overload of Public (instead of Private).

Public Sub UpdateTarget(ByVal Value As TargetOne)

End Sub

Public Sub UpdateTarget(ByVal Value As TargetTwo)

End Sub

Now it works!

, Object , , - , .

- ?

( !)

. Ive ( UpdateTarget Public), . TypeOf objTarget, DirectCast UpdateTarget, ...

For Each objTarget As Object In Targets
    If TypeOf objTarget Is TargetOne Then
        UpdateTarget(DirectCast(objTarget, TargetOne))
    ElseIf TypeOf objTarget Is TargetTwo Then
        UpdateTarget(DirectCast(objTarget, TargetTwo))
    End If
Next

- , , UpdateTarget Private to Public , !

+3
4

, , , . TargetOne/Two , - , .

, ... , .

# , TargetBase TargetOne TargetTwo... - , . , , VB.NET.

, , VB VB.NET - , : http://msdn.microsoft.com/en-us/library/tb18a48w.aspx

Option Strict VB.NET 2010. , : http://msdn.microsoft.com/en-us/magazine/ee336029.aspx

: , , , .

2:, , ( / ) IL Reflector. , - , - - , , .

3: , . :

" , , ."

http://visualbasic.about.com/od/usingvbnet/a/earlybind.htm

, TargetBase, . , , :

http://msdn.microsoft.com/en-us/library/h3xt2was(VS.80).aspx

. , , - , VB.NET: -)

+5

VB , , .

UpdateTarget(objTarget), objTarget TargetBase. VB :

  • "". TargetManager.
  • - objTarget. TargetBase.
  • , , , UpdateTarget .
  • , UpdateTarget TargetBase .
  • .

objTarget Object. VB .

  • Object.
  • , .
  • - , Strict , , .
  • , . ? , TargetManager. , TargetManager , ? . . , VB , TargetManager, , . , , .

, .

:

  • strict on.

  • . , , , . , .

, VB, # :

public void UpdateTargets(IEnumerable<TargetBase> targets) 
{
    foreach(var targetOne in targets.OfType<TargetOne>())
        UpdateTarget(targetOne);
    foreach(var targetTwo in targets.OfType<TargetTwo>())
        UpdateTarget(targetTwo);
}

. , TargetOnes, TargetTwos.

( , - List, IEnumerable, .)

+3

, , . : UpdateTarget , Target. , UpdateTarget objTarget.

, . TargetManager , , . , , TargetThree, TargetManager, .

+2

. , , TargetManager, UpdateTarget, TargetBase. . ...

If TypeOf x Is A Then
    DoSomething(DirectCast(x, A))
ElseIf TypeOf x Is B Then
    DoSomething(DirectCast(x, B))
End If

... .

, :

Public Class TargetManager
    Public Sub UpdateTarget(ByVal target As TargetBase)
        Dim t1 = TryCast(target, TargetOne)
        If t1 IsNot Nothing Then
            UpdateTargetOne(t1)
            Return
        End If

        Dim t2 = TryCast(target, TargetTwo)
        If t2 IsNot Nothing Then
            UpdateTargetTwo(t2)
            Return
        End If
    End Sub

    ' I would also recommend changing the targets parameter type here '
    ' to IEnumerable(Of TargetBase), as that is all you need to do '
    ' a For Each loop. '
    Public Sub UpdateTargets(ByVal targets As IEnumerable(Of TargetBase))
        For Each objTarget As TargetBase In Targets
            UpdateTarget(objTarget)
        Next
    End Sub

    Private Sub UpdateTargetOne(ByVal target As TargetOne)
        ' Do something. '
    End Sub

    Private Sub UpdateTargetTwo(ByVal target As TargetTwo)
        ' Do something. '
    End Sub
End Class

You have polymorphism back.

From the very beginning, I intuitively think that you really want this to work:

Public MustInherit Class TargetBase
    Protected Friend MustOverride Sub Update()
End Class

Public Class TargetOne
    Inherits TargetBase

    Protected Friend Overrides Sub Update()
    End Sub
End Class

Public Class TargetTwo
    Inherits TargetBase

    Protected Friend Overrides Sub Update()
    End Sub
End Class

Public Class TargetManager
    Public Sub UpdateTargets(ByVal Targets As List(Of TargetBase))
        For Each objTarget As TargetBase In Targets
            objTarget.Update()
        Next
    End Sub
End Class
+1
source

Source: https://habr.com/ru/post/1754820/


All Articles