Consider this code fragment:
public void Run()
{
var caseInsensitiveParser = new Parser(with =>
{
with.CaseSensitive = false;
with.IgnoreUnknownArguments = true;
with.HelpWriter = Console.Error;
});
try
{
options = caseInsensitiveParser.ParseArguments<HorizonAppOptions>(commandLineArguments);
if (options.Errors.Any()) { errorMessages.Add("Unable to process command line arguments."); }
}
catch (Exception ex)
{
errorMessages.Add(ex.Message);
}
IHorizonExporter exporter = null;
IHorizonImporter importer = null;
try
{
if (!string.IsNullOrWhiteSpace(options.Value.Importer))
{
importer = GetImporter();
importer.ProcessCommandLineArguments(caseInsensitiveParser, commandLineArguments);
}
}
catch (Exception ex)
{
errorMessages.Add(ex.Message);
}
try
{
if (!string.IsNullOrWhiteSpace(options.Value.Exporter))
{
exporter = GetExporter();
exporter.ProcessCommandLineArguments(caseInsensitiveParser, commandLineArguments);
}
}
catch (Exception ex)
{
errorMessages.Add(ex.Message);
}
if (importer==null || exporter==null)
errorMessages.Add("Both an importer and an exporter must be specified.");
if (errorMessages.Any())
{
foreach (var errorMessage in errorMessages) { Console.WriteLine(errorMessage); }
DisplayImportersAndExporters();
Environment.Exit(-1);
}
else
{
// Perform the import and the export.
var horizon = importer.ImportHorizon();
exporter.ExportHorizon(horizon);
}
}
I'm hitting the second catch()
clause and getting some very odd results. The exception originates from an attempt to open a file that doesn't exist. I expect to get a DirectoryNotFoundException
, but inside the catch block I see that ex
is actually null, as you can see from the data tip:
Huh? How can the caught exception be null? Surely that's an oxymoron, if I'm inside a catch block, the exception can't be null?
Now wait a minute... In the debugger's Locals window, there's this:
What?? How can there be three variables with the same name all in scope?
Am I losing my sanity? I'm positive this is a pattern I've used for many years without problems...
UPDATE
Yuriy Faktorovich suggested in the comments that .NET exception caught is unexpectedly null might be relevant. I think he is on to something, as I am using Code Contracts in the solution but not in this particular method. It does seem like Code Contracts are implicated though. One of the responders to that other question suggested that renaming the variables worked and, indeed it does. If I call them ex1
, ex2
and ex3
then all is well. I think there is a subtle difference in the IL when CCREWRITE has been used and the debugger is getting confused.