5

I am testing my run() function to make sure it has all the correct things populated by the end of the method. I populate 4 fields from our databases, two strings, and two IEnumerable(string)'s. The idea is to print them all out for all the people I am pulling from the database.

When I only print the string fields, everything works fine. However, when I try to add the Enumerables as well, nothing prints at all. I am also printing a counter so I know the program is still running and working. Does Console ever decide to not print anything at all due to space or something else?

Here's the code that does it:

int i = 0;
foreach (Contact contact in Contact.LoadWithPredicate(getAll))
        {
                -------other code to populate fields---------

                i ++;
                Console.WriteLine(i);
                //Turn the Enumerables into strings for printing
                string firstEnumAsString = String.Join(", ", firstEnumerable.ToArray());
                string secondEnumAsString = String.Join(", ", secondEnumerable.ToArray());

                Console.WriteLine("Email: " + firstString+ ", correspondance: " + secondString+ ", PAM addresses: " + firstEnumAsString+ ", famousPeople: " + secondEnumAsString);
}

So, as my output, whenever I run the code above, I get an output like this:

1

2

Email: foo@bar.com, correspondance: John, PAM addresses: bar@foo.com, famousPeople: foo, bar, foo

3

4

etc

Problem is, only two people out of the total (~425) show up, the rest of the lines are just numbers. Shouldn't I at least get the strings "Email", and ", correspondence"? It seems like Console is just deciding not to do anything. And I know that the code must reach it because it prints out the integer i just before I call that Console.WriteLine().

On the other hand, whenever I just ask for the two string fields to be printed, the Console displays both fields for all 425 users, right after their corresponding integer. Does anyone know what's happening here? TIA

Alex Chumbley
  • 754
  • 3
  • 10
  • 14
  • Console.Write can fail if whatever is listening to it fails. Do you have any custom listeners attached or are you just running this from the command line? – Jonathan Allen Jul 05 '13 at 21:26
  • no time to test it, but in some runtimes if you concat with a null, the final result is null. Any null in the thing your are Joining? – MatthewMartin Jul 05 '13 at 21:27
  • Set a break point at line your `Console.WriteLine`, and check do all variables have values ? – Shaharyar Jul 05 '13 at 21:28
  • I might as well be running it from the command line, all this method really does is load a list of people and take out some of their attributes. What seems most weird to me is that it works for two of the people in the scenario when I only print the string attributes. The loop is the same for each person, so I have no idea why the Console would discriminate at all between them – Alex Chumbley Jul 05 '13 at 21:30
  • Have you tried stepping through with a debugger? What happens on the non printed lines? Do you see anything odd in the variables if you inspect the text in the debugger (something line a null `\0`) – Scott Chamberlain Jul 05 '13 at 21:30
  • Not all the variables need to have values, but does that matter? I've concatenated with null before without problems. – Alex Chumbley Jul 05 '13 at 21:31
  • use `string temp = String.Format("{0} {1}", p1, p2);` Easier to debug as well. – H H Jul 05 '13 at 21:32
  • Yes, that is one of the reasons why you should use `String.Concat` instead of `+` – Scott Chamberlain Jul 05 '13 at 21:33
  • Console.Write can throw and IOException. – Botonomous Jul 05 '13 at 21:34
  • 3
    String concatenation in C# is specified as treating null as an empty string, so unless the framework has a bug, that can't be it. Source: http://msdn.microsoft.com/en-us/library/ms228504.aspx –  Jul 05 '13 at 21:34
  • 2
    As far as I know, `+` will call `String.Concat` anyway (and will convert null to String.Empty). – Chris Jul 05 '13 at 21:35
  • I'd like to know under which conditions the "+" operator with strings results in a `null` result since I've never personally seen it. (I know the compiler can convert them to `String.Concat` calls, so I wonder if that has any effect) – Chris Sinclair Jul 05 '13 at 21:35
  • 1
    @ScottChamberlain - there is no difference (just notation). – H H Jul 05 '13 at 21:36
  • @AlexChumbley: Can you move the string concatenation in your `Console.WriteLine` to a local temporary variable, then set a breakpoint with a condition of when that value is `null` or whitespace/empty? Maybe something else is going on. – Chris Sinclair Jul 05 '13 at 21:38
  • Interesting, I took @Henrik Holterman's approach, but I got the same results – Alex Chumbley Jul 05 '13 at 21:39
  • 1
    @AlexChumbley - it's not Console.Write() . There's something (control chars maybe) in your data. – H H Jul 05 '13 at 21:39
  • And what does the debugger tell you? – H H Jul 05 '13 at 21:39
  • 2
    @AlexChumbley: Also, is this the _exact_ code in your program? You wouldn't happen to have a `try/catch` that's swallowing an exception, eh? – Chris Sinclair Jul 05 '13 at 21:40
  • i think the entire section of code needs to be available in order to figure this out – Kevin Nacios Jul 05 '13 at 21:41
  • You're right, I've been logging my catches out error Server, but I just printed them to the Console and every time that nothing is printed, I get a "value cannot be null" error. I guess from looking at @Aevitas's answer that that error will not allow me to print. – Alex Chumbley Jul 05 '13 at 21:46
  • @AlexChumbley: I don't see how you can get that though. Is it possible that `firstEnumerable` or `secondEnumerable` are `null` themselves? That would correspond with the error you would receive when attempting to call the `.ToArray()` extension method. – Chris Sinclair Jul 05 '13 at 21:51
  • Yes, Console.Write can fail but it's so unlikely that you shouldn't even consider it possible. Remember "select isn't broken" and you'll find your real problem much faster (and look humble doing so). http://www.codinghorror.com/blog/2008/03/the-first-rule-of-programming-its-always-your-fault.html – Mark Brackett Jul 05 '13 at 22:30

2 Answers2

4

Based on your comments, I think either your firstEnumerable or secondEnumerable objects are null. But since you did not post how you obtain these objects, I can't comment on why they are null or how to fix it.

It's okay for them to contain null entries, or even be fully empty, but they themselves cannot be null or it will throw an ArgumentNullException when you call .ToArray() on them. This corresponds with the "value cannot be null" exception message you're seeing.

The reason why it's not crashing and burning hard is because you are swallowing (and logging?) the exceptions within your iteration loop with a try/catch block that was not posted in your code sample.


I'm guessing your actual code is something like this:

foreach (Contact contact in Contact.LoadWithPredicate(getAll))
{
    try
    {
        ...

        object[] firstEnumerable = null;
        object[] secondEnumerable = null;

        //some logic gates here which under some circumstances do not 
        //assign a valid instance to firstEnumerable or secondEnumerable

        ...
        Console.WriteLine(i); //this prints every time

        //Turn the Enumerables into strings for printing
        string firstEnumAsString = String.Join(", ", firstEnumerable.ToArray()); //exception here
        string secondEnumAsString = String.Join(", ", secondEnumerable.ToArray()); //or exception here

        Console.WriteLine("Email: " + firstString+ ", correspondance: " + secondString+ ", PAM addresses: " + firstEnumAsString+ ", famousPeople: " + secondEnumAsString);
        ...
    }
    catch
    {
        //maybe some logging? maybe not?
    }
}

This will print out the i value each time. But when it attempts to create firstEnumAsString or secondEnumAsString it throws an exception and never hits your second Console.WriteLine("Email: " + ...); thus producing the output you're seeing. It's not that the Console.WriteLine is failing, it's that you're never calling it in the first place.

Chris Sinclair
  • 22,858
  • 3
  • 52
  • 93
2

If value is null, only the line terminator is written to the standard output stream. For more information about the line terminator, see the Remarks section of the WriteLine() method. - Source

On top of that, if one of the values you're trying to write to the console throw an Exception, like in the following code:

    private static string SomeVal { get { throw new Exception(); } }

    Console.WriteLine("Foo");
    Console.WriteLine("This throws an exception: " + SomeVal);

"This throws an exception:" won't be written to the console either; the entire string is just considered null. To me it looks like that's what's actually happening in your code; one of the values you're trying to write to the console is throwing an Exception, and it's handled somewhere silently. Are you running this code in a supressive try/catch clause?

You can easily figure out if that's the case by putting a breakpoint on Console.WriteLine or the trailing } and check the values of firstString, secondString and see if they're null. You can also tell whether one of the values you're trying to write threw an exception.

Also, you should consider using string.Format(string format, params object[] args) rather than concatenating with +. Makes debugging your code a lot easier, too.

aevitas
  • 3,753
  • 2
  • 28
  • 39
  • Thanks @Aevitas, I appreciate it. Is there any way that I can just get the console to write out null in those fields instead of making the entire string null? – Alex Chumbley Jul 05 '13 at 21:48
  • 2
    @AlexChumbley use the format `firstString ?? "NULL"` it's called the [null-coalescing operator](http://msdn.microsoft.com/en-us/library/ms173224.aspx), if the variable is null it replaces it with whatever is after the `??`. – Scott Chamberlain Jul 05 '13 at 21:51
  • Problem being is that if my assumptions are correct and the values actually do throw exceptions, their values aren't `null` - they actually have no value and when checking for `null`, they will simply be skipped during execution. – aevitas Jul 05 '13 at 21:53