GOTCHA #16 Default of Option Strict (off) isn't goodC# is a strongly typed language. VB.NET, on the other hand, is not by default, unless you turn on the Option Strict option. When you create a VB.NET project in Visual Studio, Option Strict is set to Off. Should you leave it as Off? Or should you consider setting it to On? I will present arguments for both sides here. Let's start with the code in Example 2-11. Example 2-11. Effect of Option Strict OffC# (OptionStrict) This concept does not apply to C#. VB.NET (OptionStrict) Public Class Program Public Sub foo() Console.WriteLine("foo called") End Sub Public Shared Sub Main() 'Very simple case Dim val As Integer = 2.3 Console.WriteLine(val) 'This one is more killing Dim obj As Program = New Object obj.foo() End Sub End Class In the above example Option Strict is Off (the default). The code first assigns a double value to an Integer variable. Then it goes on to assign an Object to a reference of type Program. This has disaster written all over it, and in fact the program fails at runtime. Its output is shown in Figure 2-10. Figure 2-10. Output from Example 2-11A compiler error would really be nice in this case. As much as possible, you want to eliminate problems at compile time, not runtime. Fortunately, the VB.NET compiler will help if you set Option Strict to On. You can do this in the project settings, as shown in Figure 2-11. Figure 2-11. Project Setting to set Option Strict to OnOnce this is set, you get the following compilation errors in the code:
Are there situations where you might prefer to have Option Strict Off? Well, not many, but sometimes it comes in handy. For instance, Option Strict Off may make for simpler code by eliminating a number of CType or DirectCast statements when interoperating with some COM components. In cases where the code is easier to write with Option Strict Off, set Option Strict to Off in the source file for those classes only. In an application that my colleagues and I developed in C#, I had to resort to writing one of the modules in VB.NET. The reason was that I had to integrate a COM component that published only the IDispatch interface. After struggling with it for hours, I could find no way to communicate with this component using C# or VB.NET with Option Strict On. To illustrate the point, Example 2-12 shows a scripting component representing a bank account. Example 2-12. An example scripting COM component<?xml version="1.0"?> <!-- Scripting Component eBankAccount.wsc --> <!-- This is a strip down from a component that does more serious work accessing a database. I have cut it down to bare minimum. --> <component> <?component error="true" debug="true"?> <registration description="eBankAccount" prog version="1.00" class > </registration> <public> <property name="balance"> <get/> </property> <method name="deposit"> <PARAMETER name="purpose"/> <PARAMETER name="amount"/> </method> <method name="withdraw"> <PARAMETER name="purpose"/> <PARAMETER name="amount"/> </method> </public> <implements type="ASP" /> <script language="VBScript"> <![CDATA[ OPTION EXPLICIT dim accountNumber dim balance balance = 0 function get_balance() get_balance = balance end function function deposit(purpose, amount) balance = balance + amount end function function withdraw(purpose, amount) balance = balance - amount end function ]]> </script> </component> I wanted to access this component from within my .NET code. I tried generating a type library from the component. However, when I used tlbimp.exe to import the type library, I got this error: TlbImp error: System.TypeLoadException - Error: Signature has invalid ELEMENT_TYPE_* (element type:0x. So how can you communicate with components like this? Because it only exposes the IDispatch interface, you can only bind to it at runtime. It has no distinct signature (methods and properties); you call all its features indirectly through the IDispatch Invoke() method. Option Strict Off and late binding through System.Object come to the rescue (see Example 2-13). Example 2-13. Using late binding to communicate with the componentVB.NET (OptionStrict) Option Strict Off Module Program Sub Main() Dim theComType As Type = _ Type.GetTypeFromProgID("eBank.Account") Dim theComponent As Object = _ Activator.CreateInstance(theComType) Console.WriteLine("Balance = {0}", _ theComponent.balance) Console.WriteLine("Depositing $100") theComponent.deposit("deposit", 100) Console.WriteLine("Balance = {0}", _ theComponent.balance) End Sub End Module In the code in Example 2-13, even though the project level setting is Option Strict On, in this class file I have set Option Strict Off. Without this setting at the top of the file, I would have gotten compilation errors when I accessed the balance property and when I invoked the deposit() method. But with Option Strict Off, I was able to dynamically create an instance of the component using the Activator.CreateInstance() method of the Type object obtained from the prog ID ("eBank.Account"). The above code produces the output shown in Figure 2-12. Figure 2-12. Output from Example 2-13IN A NUTSHELLSet Option Strict to On to improve type checking of your VB.NET code. On rare occasions, you may find setting Option Strict Off to be of benefit, especially when you need to interoperate with late-binding COM Components exposing only the IDispatch interface. In these cases, set Option Strict Off only in those isolated files (classes) that interact with the components. SEE ALSOGotcha #70, "Spattering access to COM components makes code hard to maintain." |