GOTCHA 26 Details of exception may be hidden


GOTCHA #26 Details of exception may be hidden

When you receive an exception, you try to figure out its cause. At times, though, the exception you get does not give you enough details, so you are left wondering what really went wrong. At these times you should look deeper into the exception object to see if more information is present in the InnerException.

Consider the XMLSerializer class, which makes the tasks of parsing and creating an XML document almost trivial in .NET. However, when it fails, it fails with style. I have found it painful to diagnose the problems. Then somehow I discovered that the actual error message is hidden in the InnerException property. Look at the example in Example 3-18.

Example 3-18. Failure of XMLSerializer

C# (XMLSerializer)

 //SomeType.cs using System; namespace XmlSerializerException {     public class SomeType     {         private int val;         public int TheValue         {             get { return val; }             set { val = value; }         }     } }  //Program.cs using System; using System.Collections; using System.Xml.Serialization; using System.IO; namespace XmlSerializerException {     class Program     {         [STAThread]         static void Main(string[] args)         {             ArrayList myList = new ArrayList();             myList.Add(new SomeType());             try             {                 using(FileStream fileStrm                           = new FileStream("output.xml",                           FileMode.Create))                 {                     XmlSerializer theSerializer                         = new XmlSerializer(                             typeof(ArrayList));                      theSerializer.Serialize(fileStrm, myList);                 }             }             catch(InvalidOperationException ex)             {                 Console.WriteLine(                     "OOps: The Problem is \"{0}\"",                      ex.Message);             }             catch(Exception catchAllEx)             {                 Console.WriteLine(                     "OOps: The Problem is \"{0}\"",                     catchAllEx.Message);                 throw;             }         }     } } 

VB.NET (XMLSerializer)

 'SomeType.vb Public Class SomeType     Private val As Integer     Public Property TheValue() As Integer         Get             Return val         End Get         Set(ByVal Value As Integer)             val = Value         End Set     End Property End Class 'Program.vb Imports System.IO Imports System.Xml.Serialization Module Program     Sub Main()         Dim myList As New ArrayList         myList.Add(New SomeType)         Try             Dim fileStrm As New FileStream("output.xml", _                 FileMode.Create)             Dim theSerializer As New XmlSerializer(GetType(ArrayList))              theSerializer.Serialize(fileStrm, myList)         Catch ex As InvalidOperationException             Console.WriteLine( _              "OOps: The Problem is ""{0}""", _              ex.Message)         Catch catchAllEx As Exception             Console.WriteLine( _              "OOps: The Problem is ""{0}""", _              catchAllEx.Message)             Throw         End Try     End Sub End Module 

In this example you create an ArrayList and populate it with one SomeType Object. Then you create an XMLSerializer and ask it to serialize the ArrayList to the file output.xml. This looks pretty straightforward. But when you execute the code, you get the exception shown in Figure 3-14.

Figure 3-14. Exception from Example 3-18


Not a very helpful message, is it? You could sit there scratching your head until all your hair falls out. If the code is a bit more complicated, it can be even more frustrating to find the real problem. But if you modify the catch statement to print the details from the InnerException property, you get more meaningful information. The modified catch block is shown in Example 3-19.

Example 3-19. Looking for InnerException

C# (XMLSerializer)

             catch(InvalidOperationException ex)             {                 Console.WriteLine(                     "OOps: The Problem is \"{0}\"",                     ex.Message);                 if (ex.InnerException != null)                 {                     Console.WriteLine(                          "The real problem is {0}",                         ex.InnerException);                 }             } 

VB.NET (XMLSerializer)

         Catch ex As InvalidOperationException             Console.WriteLine( _              "OOps: The Problem is ""{0}""", _              ex.Message)             If Not ex.InnerException Is Nothing Then                 Console.WriteLine( _                     "The real problem is {0}", ex.InnerException)             End If 

In addition to displaying the information from the exception, it also displays details of its InnerException. The output after the code change appears in Figure 3-15.

Figure 3-15. Detailed error reported from change in Example 3-19


The inner exception clearly tells you what the problem is, and now it seems obvious: the XmlSerializer has no idea what types of objects will be held in the ArrayList. Now this is disappointingif you specify all the types that may be in the ArrayList then the code is non-extensible; it will violate the Open-Closed Principle (See the sidebar "The Open-Closed Principle (OCP)" in Gotcha #23, "Copy Constructor hampers exensibility," for more details on this principle.) In this case, you have to use the XmlInclude attribute to indicate what types the ArrayList can hold. (You will have to change the attribute declaration if you decide to add an object of a new type to it. But that is another problem.) The point here is that you can get the information about what went wrong by examining the InnerException of the received exception.

An easy way to examine the InnerException of an exception is to use the Exception.ToString() method to display its information, instead of using its Message property. (See Gotcha #15, "rethrow isn't consistent.")

IN A NUTSHELL

Look at the InnerException for a fuller understanding of the problem when you receive an exception. In general, examine the InnerException if there is one. If you will be logging an exception, remember to log not only the exception details, but the InnerException information as well. And remember that the InnerException is itself an Exception; it might contain its own InnerException.

SEE ALSO

Gotcha #15, "rethrow isn't consistent" and Gotcha #23, "Copy Constructor hampers exensibility."



    .NET Gotachas
    .NET Gotachas
    ISBN: N/A
    EAN: N/A
    Year: 2005
    Pages: 126

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net