Answered by:
Strange behavior of if condition

Question
-
Doesanyone can tell mewhy this code does not make me out of my sub...
If Prenom_tb.Text.Trim Is String.Empty Then Exit Sub End If
When in my execution window I get this result
? Prenom_tb.Text.Trim Is String.Empty True
However, with this code I leave the sub
If Prenom_tb.Text.Trim = String.Empty Then Exit Sub End If
Thanks,
Thursday, March 8, 2012 8:51 AM
Answers
-
dont use "Is" with strings
The CLR is using what is called the Intern Pool to store the values of the strings
In this process, is two strings are equals, the CLR will not put in memory two copy of the same strings, instead, it will set the 2 string objects to the same reference, a single copy of the string literal in memory.
However, depending from where the string is coming from, the process of setting the two object to the same reference may not be done immediatly, or may not be done at all.
And to make this even more difficult, different version of the Framework does have different behaviour about this.
so, if a string "IS" another string, is something that is very difficult to predict, something that will not follow the logic of your program and something that may change from computer to computer depending on the framework version installed
- Proposed as answer by Cor Ligthert Thursday, March 8, 2012 1:12 PM
- Marked as answer by Youen Zen Friday, March 16, 2012 8:19 AM
Thursday, March 8, 2012 11:26 AM
All replies
-
The IS test if the objects are the same.
The = test the content.
Success
Cor
- Edited by Cor Ligthert Thursday, March 8, 2012 10:05 AM if objects are the same
Thursday, March 8, 2012 9:14 AM -
Ok but the following condition is 'true' so why it doesn't exit the sub?
Prenom_tb.Text.Trim Is String.Empty
If Prenom_tb.Text.Trim Is String.Empty Then Exit Sub End If
Thx
Thursday, March 8, 2012 9:43 AM -
Changed my reply.
IS is the case if it is about the same objects for types is the ISTypeOf
What does execution window mean?
I get false
Success
Cor- Edited by Cor Ligthert Thursday, March 8, 2012 10:06 AM
Thursday, March 8, 2012 10:06 AM -
When I execute the code in debug mode, the condition's result is 'True'.
There is nothing in my TextBox control.
It does not exit the sub.
Thursday, March 8, 2012 10:09 AM -
Strange for me it is false if I test your code, so tell where it is True?
Success
CorThursday, March 8, 2012 10:19 AM -
After F10:
Thursday, March 8, 2012 10:27 AM -
Success
CorThursday, March 8, 2012 11:00 AM -
The test returns True. Both expressions are type String.
Thursday, March 8, 2012 11:19 AM -
dont use "Is" with strings
The CLR is using what is called the Intern Pool to store the values of the strings
In this process, is two strings are equals, the CLR will not put in memory two copy of the same strings, instead, it will set the 2 string objects to the same reference, a single copy of the string literal in memory.
However, depending from where the string is coming from, the process of setting the two object to the same reference may not be done immediatly, or may not be done at all.
And to make this even more difficult, different version of the Framework does have different behaviour about this.
so, if a string "IS" another string, is something that is very difficult to predict, something that will not follow the logic of your program and something that may change from computer to computer depending on the framework version installed
- Proposed as answer by Cor Ligthert Thursday, March 8, 2012 1:12 PM
- Marked as answer by Youen Zen Friday, March 16, 2012 8:19 AM
Thursday, March 8, 2012 11:26 AM -
It is possible to demonstrate the inconsistency between the run-time and the immediate evaluation of the expression:
- Edited by Acamar Thursday, March 8, 2012 10:28 PM Image corrected.
Thursday, March 8, 2012 8:50 PM -
And after executing the assignment? :)
Armin
Thursday, March 8, 2012 10:00 PM -
And after executing the assignment? :)
The same! Which is fortunate because if it wasn't then I would have absolutely no explanation for the oddity.
I have fixed the image.
Thursday, March 8, 2012 10:24 PM -
That's really strange - and interesting.
I've played a bit with it... You can even fool it by adding the expression
TextBox1.Text Is String.Empty & "abc".Substring(0,0)
to the watch window. Guess what it says... TRUE. lol The references can never be equal.
Armin
Thursday, March 8, 2012 10:57 PM -
If the intern pool is slightly out of step with the code (as CrazyPennie suggests) then it is possible that the runtime comparison detects two strings as not referring to the same object, while the immediate or watch comparison occurs only after the intern pool has been brought up to date, and the result will be True. That's the 'explanation' I referred to. I'm not entirely convinced, but it sounds plausible.
The problem is that the oddity only occurs with empty strings: the intern table appears to be up to date for any use of Is with a non-empty string, even when the values are literals or expressions
Dim B As Boolean = "ABC" Is "A" & "B" & "C"So it's really an issue of empty strings and Nothing. This comment probably explains it, although i can't see the exact connection:
"In the .NET Framework version 3.5 Service Pack 1, the Intern method reverts to its behavior in the .NET Framework version 1.0 and .NET Framework version 1.1 with regard to interning the empty string. In the following example, the variable str1 is assigned a reference to Empty, and the variable str2 is assigned the reference to Empty that is returned by calling the Intern method after converting a StringBuilder object whose value is Empty to a string. Then the references contained in str1 and str2 are compared for equality. "
http://msdn.microsoft.com/en-us/library/system.string.intern.aspxThursday, March 8, 2012 11:53 PM -
Crazy is exactly right (been there, done that).
Test it using a math expression:
If Prenom_tb.Text.Trim <> "" Then
' Whatever
End IfFriday, March 9, 2012 12:36 AM -
As additional information (this doesn't say a lot but here it is), check out this MSDN document. The following pretty well sums it up though:
"Because you're actually comparing ANSI values when you compare two strings, you can use the same comparison operators that you would use with numeric expressions — greater than (>), less than (<), equal to (=), and so on. In addition to these numeric comparison operators, you can use the Like operator, which is specifically for use in comparing strings, including strings that contain wildcard characters."
Friday, March 9, 2012 12:45 AM -
I'd say that (nothing IsNot string.empty)
Option Strict On Public Class Form1 Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load Dim a As String If a Is String.Empty Then Stop End If a = String.Empty If a Is String.Empty Then Stop End If 'any how I'd do it like this If String.IsNullOrWhiteSpace(a) Then End If End Sub End Class
- Edited by TechNoHick Friday, March 9, 2012 2:24 AM
Friday, March 9, 2012 2:19 AM -
That's really strange - and interesting.
I've played a bit with it... You can even fool it by adding the expression
TextBox1.Text Is String.Empty & "abc".Substring(0,0)
to the watch window. Guess what it says... TRUE. lol The references can never be equal.
Armin
Armin,
I see that I was testing the property and not the method. With the method I get also this.
Your interest is more than mine in this area (using Is is simply wrong for this expression so why investigate what gives this result).
However, if I had the same intention to investigate this kind of things like you, I would look if the String (a shared object) returns an object in his method. Probably it uses for all tests the same object, so all methods return the same shared object and therefore the IS is the same.
But I'm not interested to test that, maybe you?
However, probably only in the immediate window, in the code the expression returns false.
:-)
Success
Cor- Edited by Cor Ligthert Friday, March 9, 2012 10:55 AM
Friday, March 9, 2012 10:52 AM -
If the intern pool is slightly out of step with the code (as CrazyPennie suggests) then it is possible that the runtime comparison detects two strings as not referring to the same object, while the immediate or watch comparison occurs only after the intern pool has been brought up to date, and the result will be True. That's the 'explanation' I referred to. I'm not entirely convinced, but it sounds plausible.
The problem is that the oddity only occurs with empty strings: the intern table appears to be up to date for any use of Is with a non-empty string, even when the values are literals or expressions
Dim B As Boolean = "ABC" Is "A" & "B" & "C"So it's really an issue of empty strings and Nothing. This comment probably explains it, although i can't see the exact connection: [...]
I'm not sure if I can follow:
- The line
Dim B As Boolean = "ABC" Is "A" & "B" & "C"
is equal to
Dim B As Boolean = "ABC" Is "ABC"
because the compiler already concatenates string literals. As the runtime interns all String literals, B is True in this case, but that's no surprise. Or is that's what you're saying? Just asking. :-)
- About the intern pool being up to date: (I know you're also guessing like we all currently do. :-D )
As long as String.Intern function isn't called, only literals are interned automatically. That would mean, that all results of String expressions in the watch window are always passed to String.Intern by the IDE. However, I wouldn't know why it should do so.
My guess (tonight) was that the IDE mixes up the "Is" operator with the "Is" keyword used in "Case Is ..." in a Select Case statement. That would mean it's not a comparison of references but like a "=" comparison. It would explain why the watch window shows "True". So I've add this to the watch window:TextBox1.Text IsNot String.Empty FALSE
Using "IsNot", I can be sure that references are compared.
Another expression in the watch window:
Object.ReferenceEquals(TextBox1.Text, String.Empty) TRUE
That's surprising and still without an explanation. Even less explainable if you do this:
Dim s1, s2 As String
s1 = TextBox1.Text
s2 = TextBox1.Text
Dim b3 = s1 Is s2 FALSE
So, the Text property obviously returns a different (new) String each time.
Armin
Friday, March 9, 2012 11:47 AM - The line
-
However, if I had the same intention to investigate this kind of things like you, I would look if the String (a shared object) returns an object in his method. Probably it uses for all tests the same object, so all methods return the same shared object and therefore the IS is the same.
But I'm not interested to test that, maybe you?
Hi Cor,
Hmm.... I can't catch it. I would test it if your intention would reach my today tired brain... :) I mean, what kind of shared object? And "returns an object".. sure, if it's not Nothing it's always an object. But I got it wrong probably.
Armin
Friday, March 9, 2012 11:54 AM -
Hi Cor,
Hmm.... I can't catch it. I would test it if your intention would reach my today tired brain... :) I mean, what kind of shared object? And "returns an object".. sure, if it's not Nothing it's always an object. But I got it wrong probably.
Armin
Armin,
I mean something like this, and I can tell you that the result of this method is definitaly not the case.
Public Class Form1 Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click If X.Armin Is X.Cor Then MessageBox.Show("We Are Equal") End If End Sub End Class Public Class X Public Shared result As resultClass Public Shared Function Armin() As resultClass resultClass.y = "Armin" End Function Public Shared Function Cor() As resultClass resultClass.y = "Cor" End Function Public Class resultClass Public Shared Property y As String End Class End Class
:-)
Success
CorFriday, March 9, 2012 12:36 PM -
I mean something like this, and I can tell you that the result of this method is definitaly not the case.
[Code]Armin
Friday, March 9, 2012 12:43 PM -
Sorry to step in a thread at the end of its life. I just wanted to add that my first instinct when testing for an empty string resulting from UI content is to use either String.IsNullOrEmpty(Prenom_tb.Text.Trim) or else String.IsNullOrWhiteSpace(Prenom_tb.Text) when using the 4.0 framework. Yes, I know it can't be null but I prefer to delegate the logic to a framework method.Friday, March 9, 2012 2:14 PM