Empty strings don't act like they're empty.

C

Clinton Pierce

I'm calling a method in another assembly that's supposed to return a
string, and possibly that string might be empty. The code looks
something like this:

string d = r.Field("date").ToString();
Console.WriteLine(count++ + " '" + d + "' --> " + d.Length);

Sometimes "d" should be empty, and sometimes it's a date string. And
in the VS.NET watch window, it's indeed empty. Except that my
diagnostic line sometimes prints just the number and the opening quote
mark. So the output looks like this:

23 '20020718' --> 8
24 '20020602' --> 8
25 '20010616' --> 8
26 '20010613' --> 8
27 '20010204' --> 8
28 '29 '30 '20020731' --> 8
31 '20010814' --> 8

The line that begins with "28" printed only the sequence number and
the opening quote. Where's the rest of it? In fact, the
Console.Writeline didn't print the newline character.

If I build a condition like this:

if (d.Length == 0)
runThisCode();

The condition is never met, although the debugger is showing that the
string has a 0 length (by putting d.Length in a watch window).

This string has no nulls and no unicode characters. Wrapping the
Console.Writeline in a try/catch block doesn't seem to indicate any
exceptions are being thrown (normally they'd be caught higher up in
this particular program).

I'm completely at a loss. Help!
 
S

Soren Staun Jorgensen

"Clinton Pierce" <[email protected]> skrev i en meddelelse

If I build a condition like this:

if (d.Length == 0)
runThisCode();

Try this instead of above code:

if( d == null || d.Trim().Length == 0)
{
runThisCode();
}

You migth have nonprintable chars in the string <10>, <13> ect.

Soren

The condition is never met, although the debugger is showing that the
string has a 0 length (by putting d.Length in a watch window).
<snip>
 
C

Clinton Pierce

A small, but complete example.

using System;

namespace DebugString
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
byte [] b = new Byte [] { 0, 0, 0, 0, 0, 0, 0, 0 };

string s = System.Text.Encoding.ASCII.GetString(b, 0, b.Length);
s.Trim(new Char [1] { '\0' });
if (s.Trim().Length == 0)
Console.WriteLine("It's empty!"); // Never runs

Console.WriteLine("S is '" + s + "' length: " + s.Length); // Looks
very odd in debugger output window if run as Win32 GUI program
if ( s == "")
Console.WriteLine("It matched!"); // Never runs
Console.WriteLine("All done.");
}
}
}

My input data are byte arrays that (at one point) represented C-strings
and may be terminated with a null. All I want out of this example is an
empty string (i.e. what you'd get from string s = String.Empty;)
 
C

Cezary Nolewajka

Great! :)

It seems that the wath evaluator has some problems with displaying or calculating the values while debugging. Great code and example.

Fortunately it seems that the code executes properly and all comparisons, trims, etc. work all right. The string s isn't really empty.

You might want to change your code in one place:
s.Trim(new Char [1] { '\0' }); -> this line actually doesn't change the 's' value, it just returns a new value which doesn't get assigned to 's' variable

so, if you change the next line to look like:

if (s.Trim(new Char [1] { '\0' }).Length == 0)
Console.WriteLine("It's empty!");

the writeline will get called.
 
J

Jon Skeet [C# MVP]

Clinton Pierce said:
A small, but complete example.
Righto.

static void Main(string[] args)
{
byte [] b = new Byte [] { 0, 0, 0, 0, 0, 0, 0, 0 };

string s = System.Text.Encoding.ASCII.GetString(b, 0, b.Length);

So, now s is an 8-character string.
s.Trim(new Char [1] { '\0' });

After this, s is *still* an 8-character string, because s.Trim(...)
doesn't change the value of s, it just returns a *new* string which is
trimmed.
if (s.Trim().Length == 0)
Console.WriteLine("It's empty!"); // Never runs

Nope, and it wouldn't - because s.Trim() is only removing whitespace,
not Unicode 0 characters.
Console.WriteLine("S is '" + s + "' length: " + s.Length); // Looks
very odd in debugger output window if run as Win32 GUI program

In a normal console, it just comes up as spaces - but how null
characters are represented will indeed depend on the environment.
if ( s == "")
Console.WriteLine("It matched!"); // Never runs

No, and it wouldn't - because s is still an 8-character string.
Console.WriteLine("All done.");
}
}
}

My input data are byte arrays that (at one point) represented C-strings
and may be terminated with a null. All I want out of this example is an
empty string (i.e. what you'd get from string s = String.Empty;)

In that case, you need to change

s.Trim('\0'); // I've removed the new char[] bit as you don't need it,
// due to it being a "params" parameter.

to

s = s.Trim('\0');

Make that change in the above program and the output is:

It's empty!
S is '' length: 0
It matched!
All done.
 
C

Clinton Pierce

Thank you very much.

I stumbled on part of the answer ("s = s.Trim('\0')" -- forgot the "s=")
before I read the other posts, but learned a few other things along the
way as well.

Thanks!

(This causes me to wonder why too MS's C# compiler doesn't warn when
you've ignored the return value on a called method like I did above.)
 
J

Jon Skeet [C# MVP]

Clinton Pierce said:
Thank you very much.

I stumbled on part of the answer ("s = s.Trim('\0')" -- forgot the "s=")
before I read the other posts, but learned a few other things along the
way as well.

Thanks!

(This causes me to wonder why too MS's C# compiler doesn't warn when
you've ignored the return value on a called method like I did above.)

Because sometimes you don't need to. For instance, ArrayList.Add
returns the index at which the item was added - but how often is that
used?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top