tags:

views:

91

answers:

3

So, I have a list containing a custom class, MyClass
MyClass has properties, which can be null (but aren't meant to be).

When this class is sorted, using a custom sorter, where the sorter accesses this null property and throws an exception, the exception is considered unhandled, even though there is a try-catch block around the sort method.

Now for some reason the exception still gets written to the console, which is what the exception handler is doing.

I have a real application with this same issue, causing my unit tests to fail, even though the exception is handled correctly and I cannot explain this.

So I have attached some sample code to explain myself better, run this from VS.

Updated Code
Results:
System.InvalidOperationException
Failed to compare two elements in the array.
Done!

So it seems to be handling my custom exception, and throwing its own?

using System;
using System.Collections.Generic;
using System.Data;

namespace TestSortException
{
    class Program
    {
        static void Main()
        {
            try
            {
                var list = new List<MyClass>
                                         {
                                             new MyClass("1"),
                                             new MyClass(null),
                                             new MyClass("fdsfsdf")
                                         };



                list.Sort(new MyClassSorter());
            }
            catch(Exception e)
            {
                Console.WriteLine(e.GetType());
                Console.WriteLine(e.Message);
            }

            Console.WriteLine("Done!");
            Console.ReadLine();

        }
    }

    class MyClassSorter : IComparer<MyClass>
    {
        public int Compare(MyClass x, MyClass y)
        {
//            try
//            {
                if (x.MyString == y.MyString)
                    return 0;
                // Unhandled??? Exception here
                if (x.MyString.Length > y.MyString.Length)
                    return 1;

                return -1;
//            }
//            catch (Exception)
//            {
//                return -1;
//            }
        }
    }

    class MyClass
    {
        private string _myString;

        public string MyString
        {
            get
            {
                if (_myString == null) throw new DataException("MyString is Null");
                return _myString;
            }
        }

        public MyClass(string myString)
        {
            _myString = myString;
        }

    }

}
+3  A: 

There's a try/catch block round the Sort method, yes - and that catch block catches the exception. In other words, Sort throws an exception and your catch block catches it. It doesn't propagate out beyond Main - so "Done!" is printed.

This is exactly what I'd expect. In what way is it "unhandled" in your experience? Were you expecting Sort not to throw the exception? It needs to do something to indicate the failure to compare two elements, and this seems to be the most appropriate course of action.

In what way are your unit tests failing? Are you deliberately giving them invalid data? How do you want your comparison code to react to invalid data? If it should ignore it (and return a comparison based on another property), then you should actively check the property rather than letting an exception propagate. In most cases I'd rather allow the exception if this indicates that there's a bug earlier on though.

EDIT: Based on your other comments, it sounds like you're doing the appropriate thing, letting the exception bubble up - but it's not clear in what way you're seeing the exception not be handled.

If you're running in the debugger, it may be breaking on the exception being thrown, but that doesn't mean it won't be handled. Try either changing your exception settings or running without the debugger.

EDIT: Yes, Sort will catch the exception and throw an InvalidOperationException instead - but you can use the InnerException property of that exception to get hold of the original one. It's unfortunate that the documentation doesn't specify this :(

Jon Skeet
Have a look at the edit, my DataException seems to be handled inside the sort, and a InvalidOperationException throw from the sort method.
PostMan
Anyway to catch based on Inner Exception? It will be a code smell if I have to add another Exception handler just for InvalidOperationException
PostMan
A: 

I assume you work with .Net Framework 4.0. The new thing there is that a NullRefenrenceException can not be caught any more (similar to OutOfMemory exception).

Vasiliy Borovyak
That's not true at all. I've just tried it, and managed to catch it with no problems. Where did you get that idea?
Jon Skeet
(I've just tested the OP's code in .NET 4b2 and it behaves exactly the same way.)
Jon Skeet
"Same way" meaning unable to catch the exception? Or what?
Vasiliy Borovyak
Meaning that the exception is caught, just as I'd expect, and just as it's caught in .NET 3.5.
Jon Skeet
Seems like you are correct. But somewhere on this site I read the info about new exception handling. And seems like that was false info.
Vasiliy Borovyak
A: 

For example, when it checks that string "1" isn't equal to null. But it wants then to compare lengths of "1" string and null => which is impossible.

mnn
Yes, PostMan is aware of this - it's what happens after the exception is thrown which he's interested in.
Jon Skeet