tags:

views:

56

answers:

3

Why is the following VB.NET code setting str to Nothing in my VS2005 IDE:

If Trim(str = New StreamReader(OpenFile).ReadToEnd) <> "" Then
    Button2.Enabled = True
    TextBox1.Text = fname
End If

OpenFile is a Function that returns a FileStream

EDIT: If the above line containing Trim is not correct, is there a way to achieve the intended result in only one line?

+5  A: 

The code is never setting str at all:

If Trim(str = New StreamReader(OpenFile).ReadToEnd) <> "" Then

This line doesn’t set str, it compares it to the result of reading the file.

In VB, the = operator has two meanings, depending on context. If used in a statement, it assigns the right-hand expression to the left-hand expression. If used in any other context (i.e. in an expression), it performs an equality comparison, not an assignment.

Thus, in VB you must write the following:

str = New StreamReader(OpenFile()).ReadToEnd()
If str.Trim() <> "" Then …

Notice that I’ve replaced the free function Trim by a method call to make the code more consistent with common .NET coding practices.

Konrad Rudolph
+1: Correct answer and fastest fingers :)
Binary Worrier
@Konrad: thanks for you answer. Why have you used () next to method calls when this is unnecessary in VB?
Craig Johnston
@Craig: VB may not enforce it, but doing it consistently may aid readability.
reinierpost
@Craig: for consistency. That way I see that it’s a method call as opposed to a variable/property. For me, that’s quite an important distinction, in particular since function calls can have side-effects.
Konrad Rudolph
A: 

Because you're not setting str, you're comparing it, then trimming the result of the comparison (basically trimming either "True" or "False"

If Trim(str = New StreamReader(OpenFile).ReadToEnd) <> "" Then

This doesn't actually set str, this breaks down to the following code

Dim str as string ' Defaults to nothing/""
Dim boolValue as bool = (str = New StreamReader(OpenFile).ReadToEnd)

If Trim(boolValue) <> "" Then 
    ' This is always true, as "True" and "False" will never = ""'
...
End If
Binary Worrier
Nitpick: `Dim str as string` does *not* set `str` to `""`, it sets it to `Nothing`.
Konrad Rudolph
@Konrad: You are of couse correct . . . as am I :) Some VB madness After `dim s as string: dim b as boolean = (S is nothing)` b is true. After `dim s as string: dim b as boolean = (S = "")` b is **also** true. You gotta love VB (or not. Dislaimer: loving VB is optional)
Binary Worrier
@Binary Worrier: The reason is simple: `=` on strings in VB doesn’t resolve to `String.Equals` but to `Microsoft.VisualBasic.CompilerServices.Operators .CompareString`: http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.compilerservices.operators.comparestring(v=VS.100).aspx which offers special treatment for `Nothing`. But just try the following: `Dim s As String: Dim b = s Is ""` to see that `s` is *not* initialized to the empty string.
Konrad Rudolph
@Konrad: Thanks for resolving that, one of my "Vb Gripes" is that it can be "too" helpful.
Binary Worrier
+3  A: 

The first thing to do when starting any VB.Net project is to make sure that Option Explicit and Option Strict are both set to true in the project settings. Only ever disable either of them if you have a specific reason (you need late binding or are taking over some old horrible code).

This would have stopped that code from even compiling and would have shown you the error right away.

ho1
I agree that using `Strict` and `Explicit` is a must but this wouldn’t have prevented the code from compiling.
Konrad Rudolph
@Konrad Rudolph: It would give an error on the `Trim` statement since it would disallow the implicit conversion from `Boolean` to `String`.
ho1
@ho1: No. The code *compares* two strings (the trimmed string and the empty string).
Konrad Rudolph
@Konrad Rudolph: No, it doesn't even get that far, it breaks earlier than that. Just try it, declare two string variables called `a` and `b` and then type the code `If Trim(a = b) <> "" Then`. VB.Net does not treat that `=` as an assignment, it treats it as a comparison.
ho1
@ho1: (1) I *know* that VB treats this as a comparison, look at my answer below. (2) VB allows passing the `Boolean` to `Trim`, even with `Option Strict On`. I *did* try it. (vbnc version 0.0.0.5914 Mono 2.4.2 - r) – Though to be honest, I’m a bit surprised myself right now. Perhaps another bug in the Mono VB compiler?
Konrad Rudolph
@Konrad Rudolph: Sounds like a bug in that case, I tried it both in VS2005 and VS2010 and neither of them accepts it.
ho1