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 exce开发者_开发技巧ption. 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
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.
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.
精彩评论