views:

39

answers:

2

Hi I am exploring ways to implement something Visitor Patterns alike without all the decorating visit methods. Sofar I found out I could use Option Strict Off in VB.NET but it has some side effects. I have a set of Shape classes that inherit from a baseclass Shape. Assume we have the following class that Accept's shapes:

Public Class ShapeAcceptor 
    Public Sub New()
      MyBase.New
    End Sub
    Public Sub AcceptShape(s as Shape)
      AcceptAny(s)
    End sub
    Private Sub AcceptAny(o as Object)
      Accept(o)
    End sub

    Private Sub Accept(byval s as Shape)
      Console.writeLine("Shape")
    End Sub 
    Private Sub Accept(byval s as Square)
      Console.WriteLine("Square")
    End sub
    Private Sub Accept(byval s as Circle)
      Console.writeLine("Circle")
    End Sub
    Private Sub Accept(byval s as Triangle)
      Console.writeLine("Triangle")
    End Sub  
  End Class

This works when Option Explicit is turned off. However a program calling the AcceptShape method with something else does compile but gives a runtime exception. How can we turn this into a compiletime Error?

Public Class Application
    Public Shared Sub Main()
      Dim acceptor as new ShapeAcceptor
      Dim env as new Envelope
      For Each s  as Shape in env.Items
        acceptor.AcceptShape(s)
      Next
      acceptor.AcceptShape(new NotAShape())
     End Sub
  End Class
A: 

When you set the class to Option Strict Off you're telling the compiler to allow late binding on that class, which is most likely not a good idea.

What you should probably do is change it to Option Strict On so you get the compile errors, and subsequently you will stop getting runtime exceptions because it will catch the incorrect parameter.

Joseph
A: 

Turning Option Strict off allowed you to make the late-bound call Accept(o).

The clean solution -- which also solves your run-time-error problem -- would be to turn Option Strict back on and do the late-bound call manually. So, basically, you would replace

Public Sub AcceptShape(s as Shape)
  AcceptAny(s)
End Sub
Private Sub AcceptAny(o as Object)
  Accept(o)
End Sub

with

Public Sub AcceptShape(s as Shape)
  GetType(ShapeAcceptor).InvokeMember("Accept", BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.InvokeMethod, Nothing, Me, new Object() {s})
End Sub

(See the documentation of Type.InvokeMember for details. You'll need Imports System.Reflection for the BindingFlags.)

This basically does the same what your Accept(o) did, except that it is "Option Strict"-compatible.

Heinzi