Posted By: Red5 | Jun 27th, 2008 @ 11:04 AM
page 1 of 2
Comments: 32 | Views: 1956
Red5
Red5
Systems Manager Curmudgen

Is this supposed to evaluate to TRUE in vb.net?
--------------------
Dim strMessage as String

If strMessage = "" Then
    'if true, do some stuff here
End If
-------------------

strMessage, in debug mode, shows a value of "Nothing".
Is "Nothing" supposed to equal a string of zero length?
I would have thought Nothing == Null.....which is different than ""

stevo_
stevo_
Human after all
VB will use its own library to do string comparisons, of which is will essentially say that, null is nothing, zero length is nothing. If you pull the IL apart, you'll find VB calling a visual basic compiler services method of some sort.

Kinda one of the reasons I don't like VB, brings a ton of crap with it (althought I think I heard you can tell the compiler not to do this now).
evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
Under C# this would definitely not be the case - (String.Empty != null). There is a static method on the string class that provides simmilar functionality:

static bool String.IsNullOrEmpty(String str);
stevo_
stevo_
Human after all

I appreciate the addition, but that really makes me sound like I've been doing .NET for 3 days or something Tongue Out

ZippyV
ZippyV
Fired Up
Kinda one of the reasons I don't like VB, brings a ton of crap with it (althought I think I heard you can tell the compiler not to do this now).

Option Strict On ?
evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
Anything you read into my comment further than the strictly technical details I provided was entirely unintentional.
stevo_
stevo_
Human after all
No, its runtime agility:

http://community.bartdesmet.net/blogs/bart/archive/2007/09/03/visual-basic-9-0-feature-focus-runtime-agility.aspx

But its more if you drastically need compilation control I guess.. plus- it doesn't stop vb from trying to call that method.. but it does mean you get to define the method yourself.
littleguru
littleguru
<3 Seattle
You could probably use:

String.Compare(strMessage, "")

to walk around the "problem" of VB.NET. This will fall back to the bahaviour that you expect.
At least in VB6 "" a.k.a. vbNullString <> Nothing, so I doubt they'd change it VB.NET.  In fact I think it would give a compiler error in VB6, since a String isn't an object and only objects can be compared with Nothing.

I just tried this in VS2008 and it does evaluate to true....wow...does 0 equal nothing too, since that's the default value of an Integer....wow that does too....who made that decision?
Sven Groot
Sven Groot
My name has 9 letters. Coincidence? I think not...
Option Strict has no bearing on the problem.

And yes, VB considers Nothing and "" to be equivalent in string comparisons. It has done so since the first version of VB.NET (can't remember how VB6 behaved). I find it a very useful behaviour as writing foo = "" is easier than String.IsNullOrEmpty(foo), which has the same effect.

If you must make the distinction, use String.Compare as Littleguru suggested.
littleguru
littleguru
<3 Seattle
You also might to want Equals...

String.Equals(strMessage, String.Empty)

if you like that more. It also returns a Boolean instead of an Integer and it's also what the == operator on String uses internally.
strMessage Is String.Empty also works.
Well, in VB.NET Nothing has a very different meaning than Null in C#.  In C#, null refers only to reference types and means there is no reference assigned to the reference variable.  Nothing, on the other hand is the default value of any particular data type or object.

Note that  String.IsNullOrEmpty is much faster then == "". If your in a loop (for example, when parsing a file) you can defiantly see the difference.

See: http://msdn.microsoft.com/en-us/ms182279.aspx

evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
And .Length == 0 is even faster if you know that the string is non-null. In fact:

static bool IsNullorEmpty(string s){
  return ((object)s == null) || (s.Length == 0);
}
stevo_
stevo_
Human after all
I think that is inferred by the example between 1.1 and 2.0 Tongue Out but yes.. any real world performance charts on it?
evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
No, but looking at the .NET source code (or using reflector) will show you that my code is identical to the method call, but without either

a) The method call
b) A comparison

So we're talking in the region of 12-25 CPU cycles (depending on the size of the instruction branching lookahead buffer on the CPU) per call.

Which adds up.
Maybe a stupid question, but can I ask why you cast to an object before comparing to null? Why not just:
return s == null || s.Lenght == 0;

Doesn't the cast cost performance?
stevo_
stevo_
Human after all
Theres no reason to cast the string.. it could be a legacy thing he's used to.. and yes the IL will contain a castclass opcode for the downcast, so it will cost performance.
TommyCarlier
TommyCarlier
I want my scalps!
That would be true, if String.IsNullOrEmpty was implemented like that. But it's not. Reflector shows us that String.IsNullOrEmpty is implemented like this in IL:
.method public hidebysig static bool IsNullOrEmpty(string 'value') cil managed
{
    .maxstack 8
    L_0000: ldarg.0 
    L_0001: brfalse.s L_000d
    L_0003: ldarg.0 
    L_0004: callvirt instance int32 System.String::get_Length()
    L_0009: ldc.i4.0 
    L_000a: ceq 
    L_000c: ret 
    L_000d: ldc.i4.1 
    L_000e: ret 
}
This translates into the following C# code:
public static bool IsNullOrEmpty(string value)
{
    if (value != null)
    {
        return (value.Length == 0);
    }
    return true;
}
evildictaitor
evildictaitor
if( !succeed( try() ) ) { while(true) try(); }
A legacy thing? The code

string s = .. ;

if(s == null)

translates to the operator overload of == for string :

if( System.String::op_eq(s, null) )

whereas the code

if((object)s == null)

is compiled directly to an integer comparison of the references against zero.

If you're compiling with optimisations on you won't see a difference (as the ilasm output shown by someone else above shows).

By the way, there is no cost in casting a object down its inheritance tree, except from a valueType or to an interface (boxing), so there is never a cost for reference types of doing comparisons with a pre-cast to object., and you end up with more obvious behaviour since it's a reference equivlence rather than an operator overload invocation.
stevo_
stevo_
Human after all
Yes I've looked at the method call in reflector before, I was specifically just referring to the sample provided.. I can't see any reason why MS would write the method as previously suggested, especially on a class that is part of the BCL..
stevo_
stevo_
Human after all
Uh no.. the IL above has nothing to with the code you wrote.. MS doesn't cast their string to an object to null check it.. and I don't know where you get this thing of casting to an object is compiled directly into integer comparison of the references.. string is a reference type and .NET will run reference equality on the same as an object.. so .NET will check if its the same memory reference if you cast it or not..

As it goes, the IL for both appears to be identical regardless of optimizations (optimizations IL being shorter but both identical)..

As for a legacy thing, I was politely meaning "twitch".. just something you cannot help but do.. but rest assured that removing useless downcasts seems to be amongst the most mediocre behavior of the compiler.. optimizations or not.. you'll just have to worry about explaining to everyone why you feel casting to object is aparently worth doing..
page 1 of 2
Comments: 32 | Views: 1956
Microsoft Communities