is there any possibility to assign a value to a variable inside an IF condition in VB.NET?
Something like that:
Dim customer As Customer = Nothing
If IsNothing(customer = GetCustomer(id)) Then
Return False
End If
Thank you
Sorry, no. On the other hand, it would get really confusing, since VB.NET uses the same operator for both assignment and equality.
If a = b Then 'wait, is this an assignment or comparison?!
Instead, just set the variable and compare:
Dim customer As Customer = Nothing
customer = GetCustomer(id)
If IsNothing(customer) Then
Return False
End If
No, I'm fairly sure this is not possible - but be thankful!
This is a "feature" of C-based languages that I would never encourage the use of, because it is probably misused or misinterpreted more often than not.
I think the best approach is to try and express "one thought per line", and resist coding that combines two operations in the same line. Combining an assignment and a comparison in this way usually doesn't achieve much other than making the code more difficult to understand.
VB doesn't do that very well, especially since assignment and comparison both use the = operator. It'd get really confusing. And since VB to some degree is designed to be newbie-friendly (The B in "BASIC" actually stands for "Beginner's"), expressions with multiple side effects are not something the language generally likes to do.
If it's essential that you be able to do it all in one line, then you could make the GetCustomer method assign to a ByRef parameter, and return a boolean saying whether the assigned value was null. But really, it's better to just assign and then compare to null.
There is no builtin support for doing this, but you could use this workaround.
Public Function Assign(Of T)(ByRef destination As T, ByVal value As T) As T
destination = value
Return destination
End Function
And then it could be used like this.
Dim customer As Customer = Nothing
If IsNothing(Assign(customer, GetCustomer(id))) Then
Return False
End If
Thinking out loud because you didn't show Customer or GetCustomer...
Dim myCust As New Customer
If myCust.GetCustomer(someID) Then
End If
Class Customer
Private _customerID As Integer
Const noCustomer As Integer = -1
Public Sub New()
Me._customerID = noCustomer 'no customer
End Sub
Public Function GetCustomer(ByVal id As Integer) As Boolean
'perform required action to get customer
'if successful then set Me._customerID to ID else set it to no customer value
Return Me.HaveCustomer
End Function
Public Function HaveCustomer() As Boolean
If Me._customerID = noCustomer Then Return False Else Return True
End Function
End Class
Yes, it is possible to assign a value to a variable inside an IF condition in VB.NET.
There is even builtin support for doing this, albeit to a limited extend:
If Interlocked.Exchange(customer, GetCustomer(id)) Is Nothing Then
Return False
End If
where the methods within the Interlocked class are intended to be used within a multi-threading environment. By design, the return value of Exchange() is the old value, rather than the new one. Thus, to obtain the rather cryptic equivalent result:
If (customer = Interlocked.Exchange(customer, GetCustomer(id)) And customer Is Nothing Then
return false
End If
All of the people stating that this is an issue as VB uses the "same operator for both assignment and equality"..
I would argue that this is not a good reason as they could simply make slightly different syntax for it... for example:
Dim[Name = Expression]
If a = Dim[qwe = 1 + 2] Then
'qwe = 3
End If
'...
a = 3
If Dim[qwe = a = 1 + 2] Then
'qwe = True
End If
Related
I have a simple report in VS2008. I have a table which is like this:
I get the results as this:
I have already wasted 2 hours sitting in front of this issue. Moreover, my colleague didn't see any mistake in this either. I am 100% certain I have no formatting on the table. The results in the field value come as a string.
What wrong am I doing in the last column's code?
P.S. I have also tried
=IIF(IsNumeric(Fields!value.Value), Fields!value.Value, Fields!value.Value)
but then the data in the third column is showed as in the first one.
It seems that for some weird reason IIF is trying to parse both True and False parts and failing CDbl() on a string, but I cannot believe this can be possible, because I haven't seen a programming language doing something like this before.
After the comments on my post, I came up with a solution by writing these two functions. These two were both used to display data and overcome the stupidity of uneditable total field.
Public Function cdblf(ByVal s As Object) As Object
If (IsNumeric(s)) Then
Return CDbl(s)
Else : Return Nothing
End If
End Function
Public Function cdbls(ByVal n As Object, ByVal s As Object, ByVal b As Boolean) As Object
If (IsNumeric(n)) Then
Return CDbl(n)
Else :
If(Not IsNothing(s)) Then
If(b) Then
Return CStr(Left(CStr(s), Len(CStr(s)) - 1))
Else : Return Nothing
End If
Else : Return Nothing
End If
End If
End Function
The usage of these functions combined should be like this:
=Code.cdbls(
Sum(Code.cdblf(Fields!value.Value)),
Fields!value.Value,
InScope("matrix1_row_name") and InScope("matrix1_column_name"))
This both solved the fact that I didn't want to sum string values and also there was no need to use IIF anymore.
What's the return value when I do an assignment?
For example, can I do this? (i.e. the assignment returns the value being assigned)
Dim a As Integer = 1
Dim b As Integer = 2
a = b = 3
The question came up when I wrote this code today:
Dim updates = GetUpdates()
While updates.Count > 0
Foo.ApplyUpdates(updates)
updates = GetUpdates()
End While
I kind of wish I could have written it this way...
While (updates = GetUpdates).Count > 0
Foo.ApplyUpdates(updates)
End While
I know it's not as clean... (and I totally never declared updates) but it got me curious about how assignments work in .NET... is it a function with a return value? If so... what does it return?
Edit
I gave the first chunk of code a try. It looks like the compiler interprets it as assigning the result of comparing b and 3 to a... which is a compiler error of course.
And for the second code chunk, I get that the operator = is not defined for what ever type updates is... i.e. it thinks it's a comparison, not an assignment.
So to add to my question, why does it work this way? Is it just because vb.net overloads the symbol = with two meanings (assignment and comparison)?
about how assignment working in .NET.
This is actually about how assignment works in VB, not in .NET.
This does not work in VB.Net. The = Operator in VB.Net merely "assigns the value on its right to the variable or property on its left."
What's the return value when I do an assignment?
As seen in the above statement, the assignment operator does not return a value in VB.Net.
Note that this differs from other .NET languages. For example, in C#, the assignment = Operator does what you're describing, and "stores the value of its right-hand operand in the storage location, property, or indexer denoted by its left-hand operand and returns the value as its result."
Dim a As Integer
Dim b As Integer
a = b = 3
Note that, with Option Strict specified, this will actually be an error: "Option Strict On disallows implicit conversions from 'Boolean' to 'Integer'."
This is because VB.Net sees this as two operations - it's basically trying to do:
Dim a As Integer
Dim b As Integer
Dim temp as Boolean
temp = (b = 3)
a = temp
So to add to my question, why does it work this way? Is it just because vb.net overloads the symbol = with two meanings (assignment and comparison)?
Well, it's how the language was designed. I suspect that you are correct, though, and since the same operator (=) is used as an assignment and a comparison is why VB was made this way. However, the original VB language was this way, and to keep the syntax for VB.Net the same (or as close as possible), I suspect this behavior was carried forward.
In Visual Basic a = b = 3 translates to something somewhat unexpected. Since VB doesn't have the == operator and instead uses = for both assignments and equality comparision, the above expression comes down to the following:
If b = 3 Then
a = True
Else
a = False
End If
Note the argument of the function is named strToothpaste. When the function is called, the variable that's passed in uses the same name.
Private Sub DoThis()
Dim strToothpaste as String
Dim booSmellsFunny as Boolean
booSmellsFunny = fnc_Fragrance(strToothpaste)
End Sub
--------------------------
Private Function fnc_Fragrance(strToothpaste As String) as Boolean
If strToothpaste Like "Dr Watson's" Then
fnc_Fragrance = True
Else
fnc_Fragrance = False
End If
End Function
Is there ever a problem with re-using the name?
If variables aren't properly limited
in scope, does echoing the names
become hazardous?
If the above is true,
then does that mean good scoping
means the names can be echoed with no
problem?
Does recursion affect
anything? (Apart from
double-checking the scopes ...)
No not at all, VBA is smart enough to determine that the parameter is a parameter scoped to the function
Yes this could be dangerous, if you are in the habit of Option Expiclit Off, which is never good for your sanity.
Yes names can be echoed with no problem with proper scoping.
Not at all.
Hope this helps.
In what situtations is it best to use reference arguments to return values?
Sub Example(byref value as integer)
value = 3
End Sub
In what situations is it best to return the value (perhaps in a structure for more complex types)?
Function Example() as integer
return 3
End Function
In general, I'd avoid using reference arguments to return values.
THe design guidelines suggest avoiding this, which is why the Microsoft code analysis tools warn you when they find it.Do not pass types by reference.
It's nearly always more maintainable to return values instead of passing arguments by reference, unless there is a very specific need to do so. If you're generating a new value, return it.
when you want to return a state or status of an operation plus the result from the operation.
think of TryParse..it returns a conversion result as true or false and it returns the converted value by a ref variable.
Dim number As Integer
Dim result As Boolean = Int32.TryParse(value, number)
Public Shared Function TryParse ( _
s As String, _
<OutAttribute> ByRef result As Integer _
) As Boolean
but other than that, as others suggested i would not use by ref a lot, it can make code very hard to read and debug.
It really depends what the function's doing. Generally, though, if there's only one return, by value is easier for the caller. They can simply do:
int foo = Example(foo)
or:
int modifiedFoo = Example(foo)
as they prefer.
What (if any) is the difference between the results of the following two versions of this VB Linq query?
' assume we have an XElement containing employee details defined somewhere else
Dim ee = From e In someXML.<Employee> _
Select New With {.Surname = e.<Surname>, .Forename = e.<Forename>}
and
Dim ee = From e In someXML.<Employee> _
Select Surname = .Surname = e.<Surname>, .Forename = e.<Forename>
ie what is the point of the New ... With syntax?
I suspect that this has a simple answer, but I can't find it - any links to suitable tutorials or Microsoft documentation would be appreciated.
The difference is that the 1st explicitly creates an anonymous type. The 2nd is a query expression, and may use an existing type rather than creating an anonymous type. From the documentation linked by Cameron MacFarland:
Query expressions do not always require the creation of anonymous types. When possible, they use an existing type to hold the column data. This occurs when the query returns either whole records from the data source, or only one field from each record.
My understanding is that there is no difference.
New With is aimed to out-of-query usage like
Dim X = New With { .Surname = "A", .Forename = "B" }
Specifically for Linq queries, you can skip New With, but it is still useful for other situations. I am not sure, however, since I do not know VB 9 :)
There is no functional difference between the two pieces of code you listed. Under the hood both pieces code will use an anonymous type to return the data from the query.
The first piece of code merely makes the use of an anonymous type explicit. The reason this syntax is allowed is that it's possible to return any type from a Select clause. But the type must be used explicitly.
Dim x = From it in SomeCollection Select New Student With { .Name = it.Name }
Joel is incorrect in his statement that the second query may use an existing type. Without an explicit type, a select clause which uses an explicit property name will always return an anonymous type.
They're called Anonymous Types.
The main reason for their use is to keep the data from a query in a single object, so the iterators can continue to iterate over a list of objects.
They tend to work as temporary types for storage in the middle of a large or multi-part LINQ query.
There is no difference. The compiler will infer the anonymous type.
You most likely want to return the Value of the elements as in e.<Surname>.Value, which returns a String instead of an XElement.
Your 2nd example could be simplified as
Dim ee = From e In someXML.<Employee> _
Select e.<Surname>.Value, e.<Forename>.Value
because the compiler will also infer the names of the members of the anonymous type.
However, if you have the following class
Class Employee
Private _surname As String
Public Property Surname() As String
Get
Return _surname
End Get
Set(ByVal value As String)
_surname = value
End Set
End Property
Private _forename As String
Public Property Forename() As String
Get
Return _forename
End Get
Set(ByVal value As String)
_forename = value
End Set
End Property
End Class
Then you could change the 1st query to produce an IQueryable(Of Employee) instead of the anonymous type by using New ... With like so:
Dim ee = From e In someXML.<Employee> _
Select New Employee With {.Surname = e.<Surname>.Value, _
.Forename = e.<Forename>.Value}
One difference is that Anonymous types aren't serializable.