Optional keyword

bri189a

Senior Contributor
Joined
Sep 11, 2003
Messages
1,004
Location
VA
While doing my intial studies of C# to VB transitioning I've noticed VB still uses the 'Optional' keyword for parameters. Is that a 'degraded' way of doing overloading; in otherwords should I be using the Overloads keyword instead? If not, then why do they allow both ways of doing things?
 
Kind of figured that, thanks PD... also, I know you are one of the senior devs that uses VB... how about the Redim / Preserve keywords, as you know C# doesn't have those and if you need to do something that requires that kind of functionality you create a new array and Array.Copy .... again, is this the preferred method and Redim / Preserve is for legacy VB?
 
I must admit if I'm using arrays Redim / Preserve are one of the very few VB6 constructs I use without feeling guilty ;)
Saying that I try to stay clear of arrays these days - often using a collection class (either provided or one code for a specific purpose) is far more flexible.
 
I thought optional was a way for setting default values for arguements? You say the argument is optional and then you give it a constant value. That way someone using the method has the option of setting a parameter, and if they don't it will get the value you set for it.

I could be confused, but I'm pretty sure I've seen that syntax used..
 
Well, yes, if you use Optional for something like

Public Function FreeFallDistance(T As Single, Optional Accel As Single = 9.8) As Single
Return 0.5 * Accel * T * T
End Function

You can overload the function twice, like this:
Public Function FreeFallDistance(T As Single, Accel As Single) As Single
Return 0.5 * Accel * T * T
End Function
Public Function FreeFallDistance(T As Single) As Single
Return 4.9 * T * T
End Function

(I even saved a multiplication without using Optional), but this is the equivalent to Optional with overloading. (If you don't set the acceleration, gravitational acceleration is used.) :)
 
Preview
Actually, that isn't completely true. You can't do both

Public Function FreeFallDistance(T As Single, Accel As Single) As Single

and

Public Function FreeFallDistance(T As Single, Optional Accel As Single = 9.8) As Single

because the differ by only optional parameters.

And as far as I can tell, the optional keyword is the only way to set a paramater to a default value. So, Optional is very much still an important part of VB.net. Though, the legacy context (overriding methods) may have changed slightly.

So what is the best practice, then? It is better to explicitly override with two functions rather than using an optional keyword for a single function. Optional should be reserved for times when the paramater truly is optional or if there is a need to set a default value for a method.

In iceplug's excellent example, maybe these methods are part of a sky diver object that represents sky divers on different planets (?). The acceleration due to gravity really isn't important outside of the method for determining the current velocity of the sky diver. Does it makes sense to declare a constant class member if it will be used only in that one function? Maybe. But gravity doesn't just change for earth (where most people sky dive), it may change for other planets (not really constant), and you still want to avoid magic numbers so in this case I think the optional parameter is a good choice.

What are some other opinions on the best practices for the optional keyword?
 
Under VB.Net optional requires you to provide a default value to be used if the parameter is omitted.
Also when using an overloaded method to simulate a default value the behaviour is supported by the runtime. Optional parameters however are not supported by the runtime and this can introduce odd behaviour.

If the optional parameter is in a classlibrary then the default value is stored in the Dlls metadata and used by the compiler at compile time. If a newer version of the DLL is deployed that changes this default value the calling applications will still use the original default; to get the app to now use the new default then it would need to be recompiled against the new classlibrary dll.
 
Sorry, I misunderstood what iceplug was saying. it's either this or those two things. I thought he meant you can overrload the function with optional paramaters in the following two ways (three total methods).

What is the preffered way to use a default value? I would think the optional keyword would be more concise. Plus you avoid code duplication or extra function calls. You can also avoid, as stated earlier, declaring constants that only make sense for one function.

What is the general concensus on Optional? And what do you mean by optional paramaters are not supported by the runtime introducing odd behaviour? Are they not implimented correctly? Is there a flaw in VB? Also, since you swapped out the DLL, why would the original default value remain? Does this mean that Dynamic Link Libraries aren't really dynamically linking? Or is the interface copied to the using application, substiting the optional paramater with the default value?
 
In the case of replacing a DLL with a newer version an Optional parameter's default value is not part of the DLL's code but part of the associated MetaData.
When an application that uses this DLL is compiled and doesn't provide a value for the optional parameter then the default value is not dynamically used by the DLL function but coded into the calling application, hence if the value changes in a newer release of the DLL the application will carry on using the original default value - the only way around this is to also recompile all clients of the DLL so they now have the new default value compiled into them.

Also one overload can call another version of the function - this prevents too much code duplication and will probably be inlined away by the JIT compiler at runtime.

e.g.
Visual Basic:
Public Function FreeFallDistance(T As Single, Accel As Single) As Single
'Do something here
End Function

Public Function FreeFallDistance(T As Single) As Single
FreeFallDistance(T, 9.98)
End Function
 
So optional is out, always overload for the shear fact that optional in a library will not disseminate changes to all using applications.

Thank you for helping to clarify how Optional works. It doesn't really make any sense as to why it would be implimented the way it is, but at least now I know. And there is (at least for users of this forum) a common best practice on Optional usage.
 
What's unfortunate about the Overloaded situation that you are showing is that the Developer loses IntelliSense/AutoComplete as to what the default value would be (9.98 in this case).

While overloading can compile to the correct Overloaded version and therefore run a wee-bit faster, I kind of agree with MSKeel that it looks like something is being lost here. :(

And I suppose, then, if 'Optional' is a b*stard child, that 'ParamArray' must be the lowliest of creatures and most definately avoided? However, both of these are Strong Typed within .Net, so, on the surface, I don't really see a problem? Obviously it's how it's implemented "below the surface" that makes the difference, I guess.


PlausiblyDamp said:
In the case of replacing a DLL with a newer version an Optional parameter's default value is not part of the DLL's code but part of the associated MetaData.
I don't mean to second guess how this is implemented, but this sounds like a terrible idea. I suppose, though, that what you are describing really is something that would "break the contract" anyway, but if the DLL does change it's default, its quite astounding that the DLL does not have complete control over this change!

Amazing... Thanks for the info P'Damp! :)
 
The framework itself does fully support optional parameters, natively. It is C# that is lacking support for them.

However this does not mean they are a good idea. The VB compiler does indeed compile in the default value of a parameter when calling the function. If you try writing a small method which takes optional parameters and disassembling it, you can see the default values and metadata associated with them.

The best practice is generally accepted to be overloading functions, which essentially does the same thing anyway. For the above example, you declare another version of the function without a gravity parameter that calls the first function passing 9.8 or whatever.
 
Thanks for the Info Divil, it all makes sense. But at the same time, Optional Parameters really can be helpful. When using the Excel Object Model, for example, there are a lot of option al parameters, so in VB.Net you can call Workbooks.Open() as follows:
Visual Basic:
Dim wb As Excel.Workbook = _
  xlApp.Workbooks.Open("C:\YourPath\YourWorkbook.xls")
But the reality is that you are dropping a lot of Optional parameters at the end. In C#, which can't do this, you are forced into the following:
Visual Basic:
Excel.Workbook wb = xlApp.Workbooks.Open( 
    "C:\\YourPath\\Yourworkbook.xls", 
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, 
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, 
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, 
    Type.Missing, Type.Missing);
This is an ugly call.

Now, the Developer can be accomodated by using Overloading. This would allow the C# call to drop all these explicit Type.Missing values. But this merely passes the burden to the Programmer, for making all these overloaded versions is definately more work than creating Optional Parameters with Default Values.

And losing IntelliSense over what these default values are seems unfortunate as well. Oh well, just have to get used to it, I guess...
 
Yeah, man. That is a huge bummer. I never thought about how C# would handle it. What an inerop nightmare. Thanks for the much needed clarification on how specificly Optional works.

Optional is just so cool...That's just the cryptic C++ programmer in me talking... It is definately not good for programming in .Net.
 
I would personally class the Excel example as a problem of not supporting Overloaded functions ;) The COM world never had them so that optional parameters where the only way to acheive this - if COM had supported overlaoded methods then MS would have provided enough versions of Open to not require all thos Type.Missing entries.
 
Back
Top