Conditional Statement Returns Exception Error - vb.net

I have this conditional statement
loRecordFieldData = CType(IIf(loRecordsAttributeCollection.ContainsKey(loMappingObject.FieldID), _
loRecordsAttributeCollection(loMappingObject.FieldID), Nothing)
the problem is when loRecordsAttributeCollection doesn't contain the FieldID it return exception error key not found instead of nothing.
Could anyone explain this and how to prevent it?
Thank you

IIf is a function, so all of its arguments will be evaluated before it’s called. Use If instead, which is a genuine inline conditional and won’t evaluate the operand that isn’t returned:
loRecordFieldData = CType(If(loRecordsAttributeCollection.ContainsKey(loMappingObject.FieldID), _
loRecordsAttributeCollection(loMappingObject.FieldID), Nothing)
If this is a dictionary, you can also use TryGetValue or wrap it in an extension method:
Dim loRecordFieldData As … ' the value type of loRecordsAttributeCollection
loRecordsAttributeCollection.TryGetValue(loMappingObject.FieldID, loRecordFieldData)
' now cast

Use If instead. IIf syntax is obsolete in vb.net

Related

Null conditional operator not working (shows "invoke is not a member of xxx")

I can't seem to find anyone else having this same issue. I have seen that you can use null-conditional operators in VB.NET. E.g.
SendNews?.Invoke("Just in: A newsworthy item...")
However, I'm getting "invoke is not a member of SendNews"
I have tried setting "Option Infer On" but still getting this error.
Any ideas? (using .net 4.6.1)
The null conditional operator is used in place of a null check. For instance, instead of this:
If SendNews IsNot Nothing Then
SendNews.Invoke("...")
End If
You can shorten it to this:
SendNews?.Invoke("...")
But, that's all it does. It does nothing to check if the object actually contains the members being accessed. If you are using late binding (Dim SendNews As Object with Option Strict Off, the rough equivalent of using dynamic in C#), the null conditional operator will not skip the method call if it doesn't exist on the object. It will still throw the same exception as it would have otherwise. Currently, the only way to check if a late-bound object contains a particular method is to catch and ignore the exception or to look for it, by string name, with reflection.

In VBA, is the syntax different when creating an object vs. not?

Apologies, this was difficult to word as a clear question.
The following line is valid:
objWord.Documents.Add Template:=templatePath
But this line is not:
Set objMergedReq = objWord.Documents.Add Template:=templatePath
I get the following compiler error:
Expected: end of statement
Why are the two interpreted differently? How do I eliminate the error? Do I need extra parentheses in case 2?
The crux is this:
objWord.Documents.Add Template:=templatePath
This is a function call, but the returned value (an object reference) is discarded and thus, the function is really used as if it were a procedure; with VBA's implicit procedure call syntax, parentheses are not present. You can use the [deprecated] explicit call syntax to require the parentheses:
Call objWord.Documents.Add(Template:=templatePath)
As you noticed, this is illegal:
Set objMergedReq = objWord.Documents.Add Template:=templatePath
Because the syntax for a function call (you're not discarding the returned value here) requires the parentheses whenever an argument list is specified:
Set objMergedReq = objWord.Documents.Add(Template:=templatePath)
If you're tempted to "just use parentheses everywhere", know that you'll run into other syntax issues, as soon as you need to specify 2 or more arguments:
MsgBox (message, vbOkOnly + vbInformation) 'illegal
That's because when arguments are surrounded by parentheses, you're really telling VBA to evaluate the contents of the parentheses as a value, and pass the result ByVal to the function/procedure, even if that function/procedure is explicitly specifying the parameter as ByRef.
you need to use parenthesis when setting, so set x=f(y)
When there is no return value, like when you use a Sub, or you ignore the return value, you don't put the parameters in parenthesis. Optionally, you can use "Call" and then put the parameters in parenthesis.
In your example,
objWord.Documents.Add Template:=templatePath
the add method does create a return value, but you are not using it. Therefore, you either don't use parentheses (as you show), or you could use the "Call" statement:
Call objWord.Documents.Add(Template:=templatePath)
In your second example, you are using the return value, so parenthesis are required:
Set objMergedReq = objWord.Documents.Add(Template:=templatePath)
The "Set" is needed because you are assigning an object. The same rules apply if the return value is a non object -- you would just omit the "Set".

How to force lazy-OR evaluation in VB.NET?

I am reading in data from a database and putting it in a DataRow.
I want to test a nullable boolean field for whether it is Null or True.
How can I do the following in VB.NET without it throwing an exception about how the Or operator cannot have DBNull as one of its operands? Can I force lazy-OR evalution so that is just evaluates the IsNull and proceeds no further?
If row.IsNull("MyNullableBooleanField") Or row("MyNullableBooleanField")
Use the 'OrElse' operator:
If row.IsNull("MyNullableBooleanField") OrElse row("MyNullableBooleanField") Then

Why does this code NOT create a Visual Studio warning about not returning a value on all code paths? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
No warning in VB.NET when function has no return
While writing the following function, I noticed that I was NOT getting a warning about not returning a value on all code paths. The CASE ELSE clause is not returning a value, so it should be giving me a warning. I tried changing the notification level from Warning to Error, but it's still not complaining about it.
Public Function LookupOccasionGroup(ByVal occasion As GCOccasionType) As GCOccasionGroups
Dim occasionInfo = _occasionTypes.FindByOccasionTypeID(occasion)
If occasionInfo Is Nothing Then
Throw New InvalidOperationException("blah blah")
End If
Select Case occasionInfo.OccasionGroupID
Case GCOccasionGroups.DineIn, GCOccasionGroups.Delivery, GCOccasionGroups.CarryOut
Return CType(occasionInfo.OccasionGroupID, GCOccasionGroups)
Case Else
Log.Warn("Blah Blah.")
End Select
End Function
You are confusing VB.NET with a different language; not assigning the return value is permitted in VB.NET. The return value is Nothing, same thing as default(T) in C#. This has always been permitted in Visual Basic.
The screenshot shows a different diagnostic, the one you get when you forget to declare the function return value type. The compiler can now no longer figure out reliably what to return when no assignment is made. It punts for Object and returns Nothing when no assignment was made. That's very likely to blow up with an inscrutable NRE exception, thrown at a location that leaves little hint where the true problem is located:
Function Foo()
End Function
You'll now get:
error BC42021: Function without an 'As' clause; return type of Object assumed.
error BC31072: Warning treated as error : Function without an 'As' clause; return type of Object assumed.
error BC42105: Function 'foo' doesn't return a value on all code paths. A null reference exception could occur at run time when the result is used.
The first two errors are generated by the "Implicit type; object assumed" condition in that same list. The third error is the one you are looking for, and the warning turned into an error by the change. You don't actually want to use this of course.
Are all the possible values of the enum contained within the first case? If so, then it is conceivable that there's enough intelligence there to believe the else will never be hit.
To test this, either add a new value to the enum, or remove one of the possible values from the first case.

VB.net if block throwing an error

My code block is below. As it turns out, rdrCurrentRate.GetString(12) is a null value, but the code block throws an error. "Data is Null. This method or property cannot be called on Null values."
My intention is to write "if rdrCurrentRate.GetString(12) is NOT NULL, then sCurrentRateType = rdrCurrentRate.GetString(12)"
What am I missing here?
If Not String.IsNullOrEmpty(rdrCurrentRate.GetString(12)) Then
sCurrentRateType = rdrCurrentRate.GetString(12)
End If
You probably want to use the IsDBNull method instead:
If Not rdrCurrentRate.IsDBNull(12) Then
sCurrentRateType = rdrCurrentRate.GetString(12)
End If
Null values are not represented by null in the data reader, but instead of a special DBNull value. The IsDBNull method will check if the column represents such a value.
Try this:
If IsDBNull(rdrCurrentRate.GetString(12))=false Then
sCurrentRateType = rdrCurrentRate.GetString(12)
End If
Hope this works.
I'm thinking about 2 possibilities
1- An exception is raised in the rdrCurrentRate.GetString
2- rdrCurrentRate.GetString returns a DBNull value, which is not the same as Nothing (or null)