I'm trying to write the return statement of my function like this
Return (Not IsDbNull(result)) And (CType(result, String) = "1")
However, when result is DbNull, it throws me an InvalidCastException
Writing (Not IsDbNull(result)) And 2/0 = 1 in my watch works so it seems to me like the CType function has something special that makes it be evaluated before the rest of expression.
am I seeing things or CType doesn't respect the evaluation order in VB.NET? Is there a way around this problem that doesn't involve splitting my expression into several parts and assigning them into variables?
You should almost always use AndAlso instead of And (and OrElse instead of Or).
A logical operation is said to be short-circuiting if the compiled
code can bypass the evaluation of one expression depending on the
result of another expression. If the result of the first expression
evaluated determines the final result of the operation, there is no
need to evaluate the second expression
And on the other hand will evaluate both expression which causes this exception:
In a Boolean comparison, the And operator always evaluates both
expressions
You could also use Convert.ToString that treats Nothing or DbNull as empty string:
Return Convert.ToString(result) = "1"
In your case - converting to string - you don't need DbNull checking and converting to string.
Code below will be enough.
Return result.ToString().Equals("1")
Because DbNull.ToString() returns empty string.
In case result returned by ExecuteScalar - where Nothing(null) value is possible, as pointed out by Tim Schmelter, you can add validation for null
Dim checkedResult = If(result, String.Empty)
Return checkedResult.ToString().Equals("1")
Or use static Object.Equals method
Return Equals(result, "1")
If result is item of DataRow type then suggest using extension method for converting values to the proper type
Dim value As Integer = datarow.Field(Of Integer)("IntegerColumnName")
Dim value As String = datarow.Field(Of String)("StringColumnName")
DataRow will return empty string if value is DbNull
I am calling CustomerQuery by customer name in order to get the Id. My code has been working for quite some time without any change. Now, it is returning the IdsException 'ResponseStream was null or empty.' Here is my code:
Dim CustomerQuery as new Intuit.Ipp.Data.Qbo.CustomerQuery
CustomerQuery.Name = CustomerName
Dim qboCustomers as IEnumerable(Of Intuit.Ipp.Data.Qbo.Customer) = CustomerQuery.ExecuteQuery(of Intuit.Ipp.Data.Qbo.Customer)(context)
If qboCustomers.Count>0 then
Return qboCustomers(0).Id.Value
Else
Return ""
End If
I believe the query should not be null or empty even if there is no match. I think the count should just be 0. Or, at least I believe it worked that way in the past. Am I wrong?
Special chars in queries causes exception. You need to handle them first.
Please see this solution for escaping special chars while querying in V3 services-
https://gist.github.com/IntuitDeveloperRelations/6582149
I am working on a new ASP.Net 4.0 data driven app. In the DAL I check for NULL values on all my data and default to the proper data when NULL. I have a strange issue going on. Two dates are coming back - on one I need the time only. The First line of code for the full date works without fail - but the second line of code errors pointing to the format string but the strange part is that it errors on NULL values which does not use the format string and just returns Date.MinValue. When the second line gets data it formats the return correctly.
Dim dr As DataRow
.TourDate = IIf(dr.IsNull("tourdate"), Date.MinValue, Format(dr("tourdate"), "MM/dd/yyyy"))
.TourTime = IIf(dr.IsNull("tourtime"), Date.MinValue, Format(dr("tourtime"), "T"))
The error comes on the second line when dr("tourtime") is NULL - the erroe is: Argument 'Expression' is not a valid value.
IIf in VB.Net does not do short-circuit evaluation, so the Format call is being executed even if the value is null.
You need to use If:
.TourTime = If(dr.IsNull("tourtime"), Date.MinValue, Format(dr("tourtime"), "T"))
This is the same issue described here: Using VB.NET IIF I get NullReferenceException
To trouble-shoot this, I would inspect the actual value stored. A datetime column that appears to be null may actually have a value.
I think you should use IsDbNull instead of IsNull.
I've got the following LINQ Statement:
Dim PSNum As Integer = 66
Dim InvSeq = (From invRecord In InvSeqDataSet.RptInvSeqDT.AsQueryable() _
Where IIf(invRecord.IsPack_NumNull(), False, invRecord.Pack_Num = PSNum) _
Select New With _
{.Inv = invRecord.Invoice_Num, .Seq = invRecord.Inv_Seq}).FirstOrDefault()
invRecord.Pack_Num is a field of type Integer. This means that when I try to access it, if it is DBNull I get a StronglyTypedException. The above code throws this exception. If, however, I remove the "invRecord.Pack_Num = PSNum" and in its place put something like "True", the code works fine.
So I guess my question is, why is that that invRecord.IsPack_NumNull() returns False when the value is in fact DBNull and what can I use as a conditional instead? I've been beating my head against the wall for a while now and I can't find a solution to this problem.
In VB.NET, IIf() evaluates every one of its arguments since it's a function, not a language statement. So inv.Record.Pack_Num = PSNum will always be evaluated.
You can use If() instead of IIf() (same syntax) which uses short-circuiting evaluation so everything will work as expected.
On a side node, be careful with And and Or which have the same behavior. Use AndAlso and OrElse instead if you need short-circuiting evaluation.
In Visual Basic, is there a performance difference when using the IIf function instead of the If statement?
VB has the following If statement which the question refers to, I think:
' Usage 1
Dim result = If(a > 5, "World", "Hello")
' Usage 2
Dim foo = If(result, "Alternative")
The first is basically C#'s ternary conditional operator and the second is its coalesce operator (return result unless it’s Nothing, in which case return "Alternative"). If has thus replaced IIf and the latter is obsolete.
Like in C#, VB's conditional If operator short-circuits, so you can now safely write the following, which is not possible using the IIf function:
Dim len = If(text Is Nothing, 0, text.Length)
IIf() runs both the true and false code. For simple things like numeric assignment, this isn't a big deal. But for code that requires any sort of processing, you're wasting cycles running the condition that doesn't match, and possibly causing side effects.
Code illustration:
Module Module1
Sub Main()
Dim test As Boolean = False
Dim result As String = IIf(test, Foo(), Bar())
End Sub
Public Function Foo() As String
Console.WriteLine("Foo!")
Return "Foo"
End Function
Public Function Bar() As String
Console.WriteLine("Bar!")
Return "Bar"
End Function
End Module
Outputs:
Foo!
Bar!
Also, another big issue with the IIf is that it will actually call any functions that are in the arguments [1], so if you have a situation like the following:
string results = IIf(Not oraData.IsDBNull(ndx), oraData.GetString(ndx), string.Empty)
It will actually throw an exception, which is not how most people think the function works the first time that they see it. This can also lead to some very hard to fix bugs in an application as well.
[1] IIf Function - http://msdn.microsoft.com/en-us/library/27ydhh0d(VS.71).aspx
According to this guy, IIf can take up to 6x as long as If/Then. YMMV.
Better use If instead of IIf to use the type inference mechanism correctly (Option Infer On)
In this example, Keywords is recognized as a string when I use If :
Dim Keywords = If(String.IsNullOrEmpty(SelectedKeywords), "N/A", SelectedKeywords)
Otherwise, it is recognized as an Object :
Dim Keywords = IIf(String.IsNullOrEmpty(SelectedKeywords), "N/A", SelectedKeywords)
On top of that, readability should probably be more highly preferred than performance in this case. Even if IIF was more efficient, it's just plain less readable to the target audience (I assume if you're working in Visual Basic, you want other programmers to be able to read your code easily, which is VB's biggest boon... and which is lost with concepts like IIF in my opinion).
Also, "IIF is a function, versus IF being part of the languages' syntax"... which implies to me that, indeed, If would be faster... if for nothing else than that the If statement can be boiled down directly to a small set of opcodes rather than having to go to another space in memory to perform the logic found in said function. It's a trite difference, perhaps, but worth noting.
I believe that the main difference between If and IIf is:
If(test [boolean], statement1, statement2)
it means that according to the test value either satement1 or statement2 will executed
(just one statement will execute)
Dim obj = IIF(test [boolean] , statement1, statement2)
it means that the both statements will execute but according to test value one of them will return a value to (obj).
so if one of the statements will throw an exception it will throw it in (IIf) anyway but in (If) it will throw it just in case the condition will return its value.
...as to why it can take as long as 6x, quoth the wiki:
Because IIf is a library function, it
will always require the overhead of a
function call, whereas a conditional
operator will more likely produce
inline code.
Essentially IIf is the equivalent of a ternary operator in C++/C#, so it gives you some nice 1 line if/else type statements if you'd like it to. You can also give it a function to evaluate if you desire.
Those functions are different! Perhaps you only need to use IF statement.
IIF will always be slower, because it will do both functions plus it will do standard IF statement.
If you are wondering why there is IIF function, maybe this will be explanation:
Sub main()
counter = 0
bln = True
s = iif(bln, f1, f2)
End Sub
Function f1 As String
counter = counter + 1
Return "YES"
End Function
Function f2 As String
counter = counter + 1
Return "NO"
End Function
So the counter will be 2 after this, but s will be "YES" only. I know this counter stuff is useless, but sometimes there are functions that you will need both to run, doesn't matter if IF is true or false, and just assign value from one of them to your variable.