Check if Optional Parameter has changed - vb.net

i have a Function with1 Parameter and 10 optional Parameters.
The optional Parameters are all nothing.
Now i want to check if a optional Parameter had changed his Value or the Function was started with an optional Parameter.
Think of it that the Parameters can have the Value Nothing then the Function returns too.
ty for your help. :D

10 parameters.. that's a bit excessive... and hard to manage.
You would be better passing a class or structure.
Checking the optional parameter is the default value is the usual method for this for determining if it is pre-set or not as in the previous answer.
You would need to pass an object by reference if you need to test if it changed while the routine was running, but if it was originally passed as "Nothing" that will not work.
Without more information on what your usage intent is, it is a little hard to answer this conclusively.

If Parameter1 Is Nothing then
'Parameter1 changed
EndIf

If your other optional parameters is nothing I trust that their reference type is a string.
The following from MSDN to check if an optional argument is present -
A procedure cannot detect at run time whether a given argument has been omitted or the calling code has explicitly supplied the default value. If you need to make this distinction, you can set an unlikely value as the default. The following procedure defines the optional parameter office, and tests for its default value, QJZ, to see if it has been omitted in the call:
Sub notify(ByVal company As String, Optional ByVal office As String = "QJZ")
If office = "QJZ" Then
Debug.WriteLine("office not supplied -- using Headquarters")
office = "Headquarters"
End If
' Insert code to notify headquarters or specified office.
End Sub
Link can be found HERE

Related

Passing an rvalue as a ByRef parameter to VB6?

Background: I've got a set of VB6 DLLs that share a common "interface". Whichever version is installed locally has members of this interface invoked via COM interop (from VB.Net code, which I suspect might matter). I noticed today that one of the invocations passes [what I understand to be] an rvalue (hereinafter "an rvalue") to a VB6 function that does not have that particular parameter defined as ByVal.
Example Code:
VB6:
Public Function VB6Function(input As String) As String
' Do interesting things with input
End Function
VB.Net:
' get an instance of the VB6 class and pass our trimmed localString to it
result = vb6Instance.VB6Function(localString.Trim())
' Do interesting things with localString
I have not yet noticed an instance of the VB6 code changing the value of input, but I also haven't done an exhaustive search of the different DLL implementations (there are several hundred).
What would happen if VB6Function did change the value of input when input is "an rvalue"? For that matter, why doesn't this method invocation simply error out when "an rvalue" is passed?
What would happen if VB6Function did change the value of input when input is "an rvalue"?
Nothing. Or rather, nothing interesting.
When the called function changes the value of its argument, it makes no difference for the insides of that function whether the argument was provided byval or byref. All that matters is that there is a variable of certain type, thus, it can be acted upon.
For that matter, why doesn't this method invocation simply error out when "an rvalue" is passed?
Why would it error out? The passed argument as correct type (string), that is all that matters.
There is no notion of an rvalue in VB.
When you pass what you would call an rvalue to a method accepting something by reference, the compiler automatically passes the reference to a temporary location where the rvalue actually resides. The method gets its value byref, the caller does not care about pointers.
localString.Trim() allocates and returns a string. It has an address and can be passed around. Your code does not explicitly capture that address, but the compiler has no problem passing it to VB6Function byref. If VB6Function changes the value, it changes what that temporary location points to, which has no observable difference because it's going to be destroyed after the call either way.
As for why some people may have preferred receiving strings byref in VBA, it's specifically to avoid copying the entire string each time when calling the function. In VB.NET it's not a problem because strings there are immutable and therefore can be passed byval without copying, but in VBA that is not the case, so a byval string needs to be cloned for the purpose of the call. People avoided that by specifying byref, even though that technically gave them the power to mess with the passed variable.

Format - Expected Array

I keep getting an error when I try to format this number. I've done it in VBA before and I tried to change the SOPID to a variant, a string, and an integer.
Dim SOPID As Integer
SOPID = DMax("file_id", "tblSOP") + 1
'Output test data
MsgBox (format(SOPID, "000"))
I have no idea what I am doing wrong.
Assuming the code was pasted directly from your IDE, the casing of format is suspicious; that would be Format, unless there's a format variable or function that's in-scope, ...and that's being invoked here.
Look for a public (could be implicitly Public, or if it's in the same module then it could also be Private) format function procedure that expects an array argument: that's very likely what's being invoked here.
Rubberduck (free, open-source; I manage this project) can help you easily identify exactly what's being invoked and an inspection would tell you about any shadowed declarations, but to be sure you can fully-qualify the function call to avoid inadvertently invoking another function that's in scope:
MsgBox VBA.Strings.Format$(SOPID, "000")
Note that there are no parentheses around the argument list of a parameterized procedure call in VBA; the parentheses you have there are surrounding the first argument and making the expression be evaluated as a value that is then passed to the invoked function: this isn't necessary.
Also note the $: the VBA.Strings.Format function takes and returns a Variant; VBA.Strings.Format$ takes and returns a String. If you aren't dealing with any Null values (an Integer couldn't be Null), consider using the String-returning alias.

Chance of breaking existing code by adding optional parameter to VB.NET function?

Is there a chance that existing code in a large project might bomb if I add a new optional parameter to a function that's used everywhere? I know I can overload the function instead and minimize the risk, but really.. what's the risk if I insist on going with an optional parameter?
Here's an example:
Public Function GetContent(ByVal URL As String, ByVal ID As String, Optional ByRef PageTitle As String = "") As String
Try
Dim web As New HtmlWeb()
Dim doc As HtmlDocument = web.Load(URL)
ID = "//div[#id='" & ID & "']"
Dim ContentNode As HtmlNode = doc.DocumentNode.SelectSingleNode(ID)
' The two lines below are the mere extent of what's new inside this function, besides the new Optional ByRef parameter in its signature
Dim PageTitleNode As HtmlNode = doc.DocumentNode.SelectSingleNode("//title")
If Not PageTitleNode Is Nothing Then PageTitle = PageTitleNode.InnerHtml
Return ContentNode.InnerHtml
Catch ex As Exception
Return "<h4> Bad. Very bad. </h4>"
End Try
End Function
PS: I'd like to comment on my question after the fact, having read others' responses below and having done some additional research myself. Originally, I didn't want to question the validity of the approach of using an optional parameter. That was something VB.NET was allowing me to do and I felt I had every right to use--besides that it was simply very convenient! But my original question had more to do with whether there may be gaps in how optional parameters are implemented, from compilation down to execution--gaps that I should consider as I design my code. I was unaware of the historical significance of the optional parameter approach in relation to the overload approach. I've learned now that it's not that there are gaps or flaws in the optional parameter approach; rather, it was a solution designed for a different and older set of concerns that was simply overridden with the advent of the Common Language Runtime. I'm using VS2013. Sure, everything compiled fine with the optional parameter approach and seemed to run fine but I wanted to confirm I wasn't potentially breaking something else by adding an optional parameter--especially since someone looked at my code and suggested I should overload the function instead. I wanted to prove why I shouldn't keep my optional parameter method. James Thorpe answered that question for me now, I think. But as Tim Schmelter asked, is there a benefit for doing it this way (optional parameters) as opposed to the overload approach? To me now the overload approach seems the best and only way, and that is because I'm using a newer set of technologies that the optional parameter approach--which was implemented for Microsoft's older Component Object Model, or COM--simply wasn't designed to address (see page 83 of the book, "Microsoft Visual C# 2013 Step By Step" by John Sharp). Particularly now, if there are external modules expecting to find the old function signature (i.e., the function parameter layout that existed before I added the new optional parameter), they'll break unless I recompile them too! That's a hindrance for me. But overloading handles this software development problem much better without need for recompilation, something only now supported by the newer Common Languange Runtime, or CLR. I suppose the optional parameter support in VB.NET is more of a historical holdover now from the old COM days--and not the very best solution for my specific requirements. I've also just learned that, "The Common Language Specification, which defines the subset of the CLR that all languages should support, explicitly disallows a reliance on optional parameters. This means they are not a candidate for use in the Base Class Library and will probably never been seen in any of the other libraries shipped as part of the .NET Framework." (from the online article, "Optional Parameters Are Gaining Ground in .NET", by Jonathan Allen). Although the rules are laxer for us regular developers that consume Microsoft technologies, I think there's something to be said for their internal decision not to rely on optional parameters. I just wanted to post and share that with you in case like me you've also come here wondering!
Within a single project? No, it should be fine. However, in the comments you said:
Let's say there were other projects calling it (there is a possibility). Would it break those if I didn't rebuild them?
Optional parameters are actually baked in at compile time, so if you have your original method signature:
Public Function GetContent(ByVal URL As String, ByVal ID As String)
And someone is calling it thusly:
GetContent(someUrl, someId)
It will be compiled into their assembly as-is. With your new optional parameter, anything calling it as above without passing in the parameter would actually get compiled as:
GetContent(someUrl, someId, "")
Note how the default value of the optional parameter has automatically been brought in. If you're rebuilding everything, it's all good. However, in those projects that are referencing this one that aren't rebuilt, they will have the original two-parameter call. Your GetContent method now requires 3 parameters at runtime - you'll get a runtime error as it can't find an overload of the function that still takes 2 parameters.
Here's how you can do it without breaking code...
Public Function GetContent(ByVal URL As String, ByVal ID As String, ByRef PageTitle As String = "") As String
' the rest of your function here
End Function
Public Function GetContent(ByVal URL As String, ByVal ID As String) As String
Return GetContent(URL, ID, "")
End Function
That way you have a version of the function with 2 parameters for the existing code and one with 3.
If you want to encourage programmers to switch to the 3 parameter version, then you can mark the 2 parameter version like this:
<Obsolete("Use the version that takes pageTitle as a 3rd parameter">
Public Function GetContent(ByVal URL As String, ByVal ID As String) As String
Return GetContent(URL, ID, "")
End Function
That will give you a compiler warning if you try to call the 2-parameter version.

What does := mean in VB?

I've been using Visual Studio and I work with VB. Now I've noticed something called text:= in the IntelliSense suggestion list it gives me when coding. I'm not sure what it is. Could anyone explain it to me?
It allows you to specify the value of a particular parameter when passing arguments to a method. Normally, the parameters are determined by the order of the arguments. For instance, if you had a method like this:
Public Sub WriteStrings(s1 As String, s2 As String)
Console.AppendLine(s1 & s2)
End Sub
You would normally just call it like this:
WriteStrings("A", "B") ' Outputs "AB"
However, you could call it with named parameters like this:
WriteStrings(s1:="A", s2:="B") ' Outputs "AB"
In that example, the only real advantage is that it is obvious, when looking at the code, which argument is being passed for each parameter. However, it also allows the interesting possibility of passing the arguments in a different order. For instance:
WriteStrings(s2:="A", s1:="B") ' Outputs "BA"
However, the most common place you'll see it is when the parameters are optional. For instance, when calling this method:
Public Sub DisplayPerson(Optional includeName As Boolean = True,
Optional includeAge As Boolean = False,
Optional includeAddress As Boolean = True)
And you want to leave the default settings for the first two parameters and just want to force includeAddress to be False, you could just call it like this:
DisplayPerson(, , False)
But that's a little confusing. Many people find it less confusing to specify the name of the parameter to make the code easier to read:
DisplayPerson(includeAddress:=False)
Since arguments to set the properties of an attribute have no particular order, it's very common to see named arguments used there as well:
<DataContract(Name:="Test")>

Optional ByVal boolean parameter is not taking its default value

I am debugging a project right now and it has a function with the following signature:
Public Function changeRemoteDirectory(ByVal newDirectory As String, Optional ByVal Direction As Boolean = True) As Boolean
MsgBox(direction)
'rest of code
End Function
I was trying to figure out what was causing this function to return a value of False when I knew that it should return True given the input that I was supplying, so I put MsgBox(direction) into the Function to see what the value of direction was when I called the Function. I called the function like this, yet I received a MsgBox that showed the value of direction to be False:
changeRemoteDirectory("/internal")
The first parameter works just fine and the code that requires it to execute works correctly, but I cannot figure out why Direction has a value of False in a situation where, I believe, it should have its default value of True. I'm not totally opposed to rewriting the Function if need be, but can anybody here discern why Direction does not have a value of True when the function changeRemoteDirectory() is called without the second parameter supplied?
It sounds like you're experiencing one of many pains that optional parameters cause.
When the code that calls changeRemoteDirectory is compiled, the optional parameter is injected into the calls just like a const would be replaced at compile time. Changes to the value of an optional parameter will not take effect without recompiling the caller.
See this article for more info.
In general, you should use method overloads instead of optional parameters. You get all of the same functionality without the pain and performance drawbacks.