GOTCHA #31 Optional parameters break interoperabilityAn optional parameter in VB.NET is a parameter that is given a value at the point of declaration. When you call a method that has optional parameters, you can choose not to provide a value for them. The compiler will substitute the default values. However, not all .NET languages support optional parameters. VB.NET allows you to declare trailing arguments as optional. C# does not. What happens to interoperability if you use optional parameters in VB.NET? Consider Example 4-1. Example 4-1. Using optional parametersC# and VB.NET (Optional) 'SomeClass1.vb part of AVBDNLibrary.dll Public Class SomeClass1 Public Overridable Sub SomeMethod(ByVal val1 As Integer, _ Optional ByVal val2 As Double = 0.0) End Sub End Class //Test.cs part of CSUser.exe using System; namespace CSUser { class Test { [STAThread] static void Main(string[] args) { AVBDNLibrary.SomeClass1 obj = new AVBDNLibrary.SomeClass1(); obj.SomeMethod(1, 2); } } } The VB.NET class SomeClass1 has a method SomeMethod() with two parameters, the second one marked Optional. You also have a C# class Test that, in its Main() method, creates an instance of the VB.NET class SomeClass1 and then calls its SomeMethod(). If you look at this example, there seems to be no problem in calling the method SomeMethod() of SomeClass1. In fact, IntelliSense displays the method signature in C# without showing any indication of default or optional arguments, as seen in Figure 4-1. Figure 4-1. C# IntelliSense for a method with optional parameterWell, there is no problem if this is the level of interoperability you are looking for. However, things get tricky if you go further. To illustrate what can happen, let's derive a C# class from SomeClass1. This is shown in Example 4-2. Example 4-2. Deriving a C# class from the VB.NET class in Example 4-1C# and VB.NET (Optional) //SomeClass2.cs part of CSLib.dll using System; namespace CSLib { public class SomeClass2 : AVBDNLibrary.SomeClass1 { public override void SomeMethod(int val1, double val2) { base.SomeMethod (val1, val2); } } } Note that the overridden method SomeMethod() takes two parameters, int val1 and double val2. Since C# does not support optional parameters, both the parameters are specified. So far so good, right? Now say you create a VB.NET class that derives from SomeClass2, as in Example 4-3. Example 4-3. Deriving a VB.NET class from the C# class in Example 4-2C# and VB.NET (Optional) 'SomeClass3.vb part of AVBDNLibrary2.dll Public Class SomeClass3 Inherits CSLib.SomeClass2 Public Overrides Sub SomeMethod(ByVal val1 As Integer, _ ByVal val2 As Double) End Sub End Class Now that SomeClass3 inherits from SomeClass2, the overridden method does not have any optional parameters. When you compile this code, you get the error shown in Figure 4-2. Figure 4-2. Error compiling code in Example 4-3The error message tells you that SomeClass3 cannot override SomeMethod() because the base version and the overridden version differ by the optional parameter. What if you try to fix this error by placing the Optional keyword in SomeClass3.SomeMethod(), as in Example 4-4? Example 4-4. Placing the Optional keyword in the overriding methodC# and VB.NET (Optional) 'SomeClass3.vb part of AVBDNLibrary2.dll Public Class SomeClass3 Inherits CSLib.SomeClass2 Public Overrides Sub SomeMethod(ByVal val1 As Integer, _ Optional ByVal val2 As Double = 0.0) End Sub End Class No go. You get the same error (see Figure 4-3). Figure 4-3. Error compiling code in Example 4-4The compiler is still not happy. Why? It's because there's a conflict here. The first-level base-class method says it needs an optional parameter. The second-level immediate base class, however, says it does not have any optional parameters (being a C# class). If you look at the MSIL generated for each of these classes using ildasm.exe, you will notice that SomeClass1.SomeMethod() in the VB.NET base class has [opt] specified. However, the method in the C# class does not. IN A NUTSHELLNot all .NET languages support optional parameters. This may lead to interoperability problems. Consider using method overloading instead of optional parameters. SEE ALSOGotcha #16, "Default of Option Strict (off) isn't good," Gotcha #30, "Common Language Specification Compliance isn't the default," Gotcha #32, "Mixing case between class members breaks interoperability," Gotcha #33, "Name collision with keywords breaks interoperability," and Gotcha #34, "Defining an array isn't consistent." |